diff --git a/src/ConfigFile.py b/src/ConfigFile.py index e1e1970..6b32068 100644 --- a/src/ConfigFile.py +++ b/src/ConfigFile.py @@ -28,15 +28,16 @@ from . import _ from Logger import log + def indent(elem, level=0): - i = "\n" + level*" " + i = "\n" + level * " " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for elem in elem: - indent(elem, level+1) + indent(elem, level + 1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: @@ -52,26 +53,26 @@ def __init__(self): def readXML(self): path = config.pushservice.xmlpath.value - + # Abort if no config found if not os.path.exists(path): - log.debug( "PushService No configuration file present" ) + log.debug("PushService No configuration file present") return None - + # Parse if mtime differs from whats saved mtime = os.path.getmtime(path) if mtime == self.mtime: # No changes in configuration, won't read again return self.cache - + # Parse XML try: etree = parse(path).getroot() except Exception, e: - log.exception( ("PushService Exception in readXML: ") + str(e) ) + log.exception(("PushService Exception in readXML: ") + str(e)) etree = None mtime = -1 - + # Save time and cache file content self.mtime = mtime self.cache = etree @@ -79,22 +80,21 @@ def readXML(self): def writeXML(self, etree): path = config.pushservice.xmlpath.value - + indent(etree) data = tostring(etree, 'utf-8') - + f = None try: f = open(path, 'w') if data: f.writelines(data) except Exception, e: - log.exception( ("PushService Exception in writeXML: ") + str(e) ) + log.exception(("PushService Exception in writeXML: ") + str(e)) finally: if f is not None: f.close() - + # Save time and cache file content - self.mtime = os.path.getmtime( path ) + self.mtime = os.path.getmtime(path) self.cache = etree - diff --git a/src/ConfigScreen.py b/src/ConfigScreen.py index 9c7da67..9494505 100644 --- a/src/ConfigScreen.py +++ b/src/ConfigScreen.py @@ -16,7 +16,9 @@ # ####################################################################### -import os, sys, traceback +import os +import sys +import traceback # Config from Components.config import * @@ -55,80 +57,81 @@ # Configuration screen class ConfigScreen(Screen, ConfigListScreen, HelpableScreen, PushServiceBase): - skinfile = os.path.join( resolveFilename(SCOPE_PLUGINS), "Extensions/PushService/skin.xml" ) + skinfile = os.path.join(resolveFilename(SCOPE_PLUGINS), "Extensions/PushService/skin.xml") skin = open(skinfile).read() def __init__(self, session): Screen.__init__(self, session) HelpableScreen.__init__(self) self.skinName = ["ConfigScreen", "ConfigListScreen"] - + from plugin import NAME, VERSION, gPushService self.setup_title = NAME + " " + _("Configuration") + " " + VERSION - + PushServiceBase.__init__(self) if gPushService: gPushService.stop() - + # Load local moduls to work on self.load() - + # Buttons - self["key_red"] = StaticText("") - self["key_green"] = StaticText("") - self["key_blue"] = StaticText("") + self["key_red"] = StaticText("") + self["key_green"] = StaticText("") + self["key_blue"] = StaticText("") self["key_yellow"] = StaticText("") - + self.help_window = None - + # Define Actions #E2 Bug self["custom_actions"] = HelpableActionMap(self, ["SetupActions", "ColorActions", "PushServiceConfigActions"], self["custom_actions"] = HelpableActionMap(self, "PushServiceConfigActions", { - "pageUp": (self.pageUp, _("Page up")), - "pageDown": (self.pageDown, _("Page down")), + "pageUp": (self.pageUp, _("Page up")), + "pageDown": (self.pageDown, _("Page down")), }, -2) # higher priority - + self["main_actions"] = HelpableActionMap(self, "PushServiceConfigActions", { - "red": (self.keyCancel, _("Exit without saving")), - "green": (self.keySave, _("Save and exit")), + "red": (self.keyCancel, _("Exit without saving")), + "green": (self.keySave, _("Save and exit")), }, -2) # higher priority self["main_actions"].setEnabled(False) - + self["main_actions_enabled"] = HelpableActionMap(self, "PushServiceConfigActions", { - "yellow": (self.showServices, _("Show Services")), - "blue": (self.showControllers, _("Show Controllers")), + "yellow": (self.showServices, _("Show Services")), + "blue": (self.showControllers, _("Show Controllers")), }, -2) # higher priority self["main_actions_enabled"].setEnabled(False) - + self["service_actions"] = HelpableActionMap(self, "PushServiceConfigActions", { - "red": (self.showMain, _("Back to main screen")), - "green": (self.testService, _("Test selected Service")), - "yellow": (self.addServices, _("Add Service")), - "blue": (self.removeServices, _("Remove Service")), + "red": (self.showMain, _("Back to main screen")), + "green": (self.testService, _("Test selected Service")), + "yellow": (self.addServices, _("Add Service")), + "blue": (self.removeServices, _("Remove Service")), }, -2) # higher priority self["service_actions"].setEnabled(False) - + self["controller_actions"] = HelpableActionMap(self, "PushServiceConfigActions", { - "red": (self.showMain, _("Back to main screen")), - "green": (self.testController, _("Test selected Controller")), - "yellow": (self.addControllers, _("Add Controller")), - "blue": (self.removeControllers, _("Remove Controller")), + "red": (self.showMain, _("Back to main screen")), + "green": (self.testController, _("Test selected Controller")), + "yellow": (self.addControllers, _("Add Controller")), + "blue": (self.removeControllers, _("Remove Controller")), }, -2) # higher priority self["controller_actions"].setEnabled(False) - + # Initialize Configuration part self.list = [] self.state = MAIN self.build() - ConfigListScreen.__init__(self, self.list, session = session, on_change = self.change) - + ConfigListScreen.__init__(self, self.list, session=session, on_change=self.change) + # Override selectionChanged because our config tuples are bigger - self.onChangedEntry = [ ] + self.onChangedEntry = [] + def selectionChanged(): current = self["config"].getCurrent() if self["config"].current != current: @@ -140,33 +143,33 @@ def selectionChanged(): for x in self["config"].onSelectionChanged: x() self["config"].selectionChanged = selectionChanged - + self.setTitle(self.setup_title) def change(self, uniqueid=None): select = self.build(uniqueid) - self["config"].setList( self.list ) - + self["config"].setList(self.list) + if select is not None: self["config"].instance.moveSelectionTo(select) def build(self, uniqueid=None): self.list = [] select = None - + def buildEntries(entries): select = None if entries: for idx, entry in enumerate(entries): - self.list.append( getConfigListEntry( entry.getNameId(), entry.getConfigEnable(), idx ) ) + self.list.append(getConfigListEntry(entry.getNameId(), entry.getConfigEnable(), idx)) if entry.getUniqueID() == uniqueid: # Select the added entry - select = len(self.list)-1 + select = len(self.list) - 1 if entry.getEnable(): for key, element, description in entry.getConfigOptions(): - self.list.append( getConfigListEntry( " " + str(description), element, idx ) ) + self.list.append(getConfigListEntry(" " + str(description), element, idx)) return select - + if self.state == MAIN: self["key_red"].setText(_("Cancel")) self["key_green"].setText(_("OK")) @@ -181,26 +184,26 @@ def buildEntries(entries): self["key_yellow"].setText("") self["key_blue"].setText("") self["main_actions_enabled"].setEnabled(False) - - self.list.append( getConfigListEntry( _("Enable PushService"), config.pushservice.enable, 0 ) ) - + + self.list.append(getConfigListEntry(_("Enable PushService"), config.pushservice.enable, 0)) + if config.pushservice.enable.value: - self.list.append( getConfigListEntry( _("Dreambox name"), config.pushservice.boxname, 0 ) ) - self.list.append( getConfigListEntry( _("Config file"), config.pushservice.xmlpath, 0 ) ) - - self.list.append( getConfigListEntry( _("Start time (HH:MM)"), config.pushservice.time, 0 ) ) - self.list.append( getConfigListEntry( _("Period in hours (0=disabled)"), config.pushservice.period, 0 ) ) - self.list.append( getConfigListEntry( _("Run on boot"), config.pushservice.runonboot, 0 ) ) + self.list.append(getConfigListEntry(_("Dreambox name"), config.pushservice.boxname, 0)) + self.list.append(getConfigListEntry(_("Config file"), config.pushservice.xmlpath, 0)) + + self.list.append(getConfigListEntry(_("Start time (HH:MM)"), config.pushservice.time, 0)) + self.list.append(getConfigListEntry(_("Period in hours (0=disabled)"), config.pushservice.period, 0)) + self.list.append(getConfigListEntry(_("Run on boot"), config.pushservice.runonboot, 0)) if config.pushservice.runonboot.value: - self.list.append( getConfigListEntry( _("Boot delay"), config.pushservice.bootdelay, 0 ) ) - - self.list.append( getConfigListEntry( _("Push errors"), config.pushservice.push_errors, 0 ) ) - - self.list.append( getConfigListEntry( _("Log to shell"), config.pushservice.log_shell, 0 ) ) - self.list.append( getConfigListEntry( _("Log to file"), config.pushservice.log_write, 0 ) ) + self.list.append(getConfigListEntry(_("Boot delay"), config.pushservice.bootdelay, 0)) + + self.list.append(getConfigListEntry(_("Push errors"), config.pushservice.push_errors, 0)) + + self.list.append(getConfigListEntry(_("Log to shell"), config.pushservice.log_shell, 0)) + self.list.append(getConfigListEntry(_("Log to file"), config.pushservice.log_write, 0)) if config.pushservice.log_write.value: - self.list.append( getConfigListEntry( _("Log file path and name"), config.pushservice.log_file, 0 ) ) - + self.list.append(getConfigListEntry(_("Log file path and name"), config.pushservice.log_file, 0)) + elif self.state == SERVICES: self["key_red"].setText(_("Main")) self["key_green"].setText(_("Test")) @@ -210,9 +213,9 @@ def buildEntries(entries): self["main_actions_enabled"].setEnabled(False) self["controller_actions"].setEnabled(False) self["service_actions"].setEnabled(True) - + select = buildEntries(self.getServices()) - + elif self.state == CONTROLLERS: self["key_red"].setText(_("Main")) self["key_green"].setText(_("Test")) @@ -222,9 +225,9 @@ def buildEntries(entries): self["main_actions_enabled"].setEnabled(False) self["service_actions"].setEnabled(False) self["controller_actions"].setEnabled(True) - + select = buildEntries(self.getControllers()) - + return select def getCurrentEntry(self): @@ -257,13 +260,13 @@ def showServices(self): def addServices(self): self.hideHelpWindow() - self.session.openWithCallback(self.addServicesCB, ChoiceBox,_("Add Service"), self.getAvlServices()) + self.session.openWithCallback(self.addServicesCB, ChoiceBox, _("Add Service"), self.getAvlServices()) def addServicesCB(self, result): module = result and result[1] if module: id = self.addService(module) - self.change( id ) + self.change(id) def removeServices(self): self.hideHelpWindow() @@ -273,7 +276,7 @@ def removeServices(self): select = current[2] slist = self.getServiceInstances() if slist: - self.session.openWithCallback(self.removeServicesCB, ChoiceBox,_("Remove controller"), list=slist, selection=select) + self.session.openWithCallback(self.removeServicesCB, ChoiceBox, _("Remove controller"), list=slist, selection=select) def removeServicesCB(self, result): service = result and result[1] @@ -288,13 +291,13 @@ def showControllers(self): def addControllers(self): self.hideHelpWindow() - self.session.openWithCallback(self.addControllersCB, ChoiceBox,_("Add Controller"), self.getAvlControllers()) + self.session.openWithCallback(self.addControllersCB, ChoiceBox, _("Add Controller"), self.getAvlControllers()) def addControllersCB(self, result): module = result and result[1] if module: id = self.addController(module) - self.change( id ) + self.change(id) def removeControllers(self): self.hideHelpWindow() @@ -304,7 +307,7 @@ def removeControllers(self): select = current[2] plist = self.getControllerInstances() if plist: - self.session.openWithCallback(self.removeControllersCB, ChoiceBox,_("Remove controller"), list=plist, selection=select) + self.session.openWithCallback(self.removeControllersCB, ChoiceBox, _("Remove controller"), list=plist, selection=select) def removeControllersCB(self, result): controller = result and result[1] @@ -315,13 +318,13 @@ def removeControllersCB(self, result): # Overwrite ConfigListScreen keySave function def keySave(self): self.hideHelpWindow() - + # Save E2 PushService config self.saveAll() - + # Build xml config and write it self.save() - + # If we need assign / "write" access import the plugin # global won't work across module scope import plugin @@ -336,7 +339,7 @@ def keySave(self): else: #global gPushService plugin.gPushService = None - + self.close() # Overwrite ConfigListScreen keyCancel function @@ -352,7 +355,7 @@ def cancelConfirm(self, result): # Make sure the configuration is still consistent gPushService.load() gPushService.start() - + # Call baseclass function ConfigListScreen.cancelConfirm(self, result) @@ -370,11 +373,11 @@ def testService(self): # Allows testing the actually not saved configuration #if self.state != SERVICES: return self.hideHelpWindow() - + # Get the selected Service current = self["config"].getCurrent() service = current and self.getService(current[2]) - + if service and service.getEnable(): self.session.open(TestConsole, service) @@ -382,11 +385,11 @@ def testController(self): # Allows testing the actually not saved configuration #if self.state != CONTROLLERS: return self.hideHelpWindow() - + # Get the selected Controller current = self["config"].getCurrent() controller = current and self.getController(current[2]) - + if controller and controller.getEnable(): self.session.open(TestConsole, controller) @@ -405,16 +408,16 @@ def __init__(self, session, test): title = "" text = "" self.test = test - + self["text"] = ScrollLabel("") - self["actions"] = ActionMap(["WizardActions", "DirectionActions"], + self["actions"] = ActionMap(["WizardActions", "DirectionActions"], { - "ok": self.cancel, - "back": self.cancel, - "up": self["text"].pageUp, - "down": self["text"].pageDown + "ok": self.cancel, + "back": self.cancel, + "up": self["text"].pageUp, + "down": self["text"].pageDown }, -1) - + # Set title and text test.begin() if isinstance(test, ServiceBase): @@ -426,22 +429,22 @@ def __init__(self, session, test): else: title = _("Testing") text = _("Nothing to test") - + self.setTitle(title) self.setText(text) - + # Starting test try: if isinstance(test, ServiceBase): - test.push( self.callback, self.errback, _("PushService Config"), _("Push test"), _("If You can see this, Your configuration is correct.") ) + test.push(self.callback, self.errback, _("PushService Config"), _("Push test"), _("If You can see this, Your configuration is correct.")) elif isinstance(test, ControllerBase): - test.run( self.callback, self.errback ) + test.run(self.callback, self.errback) except Exception, e: text = _("PushService Test exception:") + str(e) + "\n\n" exc_type, exc_value, exc_traceback = sys.exc_info() for line in traceback.format_exception(exc_type, exc_value, exc_traceback): text += line - log.exception( text ) + log.exception(text) self.setText(text) def callback(self, *args): diff --git a/src/Controller/APTUpdateNotification.py b/src/Controller/APTUpdateNotification.py index adb5eb0..ad08607 100644 --- a/src/Controller/APTUpdateNotification.py +++ b/src/Controller/APTUpdateNotification.py @@ -33,20 +33,20 @@ # Constants SUBJECT = _("APT Update Notification") -BODY = _("There are updates available:\n%s") +BODY = _("There are updates available:\n%s") class APTUpdateNotification(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - + # Default configuration - self.setOption( 'selfcheck', NoSave(ConfigYesNo( default = False )), _("Start update check if not done yet") ) - + self.setOption('selfcheck', NoSave(ConfigYesNo(default=False)), _("Start update check if not done yet")) + self.data = "" self.container = eConsoleAppContainer() try: @@ -75,38 +75,37 @@ def opkgupgradable(self): self.container.execute("apt-get --just-print upgrade") def aptupgradableFinished(self, retval=None): - + try: - log.debug( "PushService retval: ",str(retval) ) + log.debug("PushService retval: ", str(retval)) except: pass try: - log.debug( "PushService self.data: ",str(self.data) ) + log.debug("PushService self.data: ", str(self.data)) except: pass - + updates = "" excepts = "" - + if self.data: try: for line in self.data.split("\n"): - log.debug( "PushService opkg upgradable data: ",line ) + log.debug("PushService opkg upgradable data: ", line) if line.startswith("Inst"): updates += line[5:] + "\r\n" continue except Exception, e: excepts += "\r\n\r\nException:\r\n" + str(e) - + if excepts: - log.exception( excepts ) - + log.exception(excepts) + if updates: #callback( SUBJECT, BODY % (updates) ) - + #TODO Problem test run won't get the message # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, BODY % (updates)) - diff --git a/src/Controller/ActiveTimers.py b/src/Controller/ActiveTimers.py index 840e5f7..7ee8b45 100644 --- a/src/Controller/ActiveTimers.py +++ b/src/Controller/ActiveTimers.py @@ -31,21 +31,21 @@ # Constants SUBJECT = _("Found active timer(s)") -BODY = _("Active timer list:\n%s") -TAG = _("ActiveTimerPushed") +BODY = _("Active timer list:\n%s") +TAG = _("ActiveTimerPushed") class ActiveTimers(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) self.timers = [] - + # Default configuration - self.setOption( 'add_tag', NoSave(ConfigYesNo( default = False )), _("Start update check if not done yet") ) + self.setOption('add_tag', NoSave(ConfigYesNo(default=False)), _("Start update check if not done yet")) def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback @@ -56,34 +56,34 @@ def run(self, callback, errback): now = time() for timer in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers: if timer.justplay: - log.debug( _("ActiveTimers: Skip justplay") + str(timer.name) ) + log.debug(_("ActiveTimers: Skip justplay") + str(timer.name)) pass - - elif str(timer.service_ref)[0]=="-": - log.debug( _("ActiveTimers: Skip serviceref") + str(timer.name) ) + + elif str(timer.service_ref)[0] == "-": + log.debug(_("ActiveTimers: Skip serviceref") + str(timer.name)) pass - + elif self.getValue('add_tag') and TAG in timer.tags: - log.debug( _("ActiveTimers: Skip tag") + str(timer.name) ) + log.debug(_("ActiveTimers: Skip tag") + str(timer.name)) pass - + elif timer.disabled: - log.debug( _("ActiveTimers: Skip disabled") + str(timer.name) ) + log.debug(_("ActiveTimers: Skip disabled") + str(timer.name)) pass - + elif timer.begin < now: - log.debug( _("ActiveTimers: Skip begin < now") + str(timer.name) ) + log.debug(_("ActiveTimers: Skip begin < now") + str(timer.name)) pass - + else: text += str(timer.name) + " " \ + strftime(_("%Y.%m.%d %H:%M"), localtime(timer.begin)) + " - " \ + strftime(_("%H:%M"), localtime(timer.end)) + " " \ + str(timer.service_ref and timer.service_ref.getServiceName() or "") \ + "\n" - self.timers.append( timer ) + self.timers.append(timer) if self.timers and text: - callback( SUBJECT, BODY % text ) + callback(SUBJECT, BODY % text) else: callback() diff --git a/src/Controller/BrokenRecords.py b/src/Controller/BrokenRecords.py index b606da5..138a855 100644 --- a/src/Controller/BrokenRecords.py +++ b/src/Controller/BrokenRecords.py @@ -30,13 +30,13 @@ # Constants SUBJECT = _("Broken records") -BODY = _("There are broken records - %s") +BODY = _("There are broken records - %s") class BrokenRecords(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) @@ -46,8 +46,8 @@ def run(self, callback, errback): # Callback should return with at least one of the parameter: Header, Body, Attachment # If empty or none is returned, nothing will be sent yesterday_end = time() - yesterday_begin = yesterday_end - 24*60*60 - + yesterday_begin = yesterday_end - 24 * 60 * 60 + broken_records = [] for root, dirnames, filenames in os.walk(config.usage.default_path.value): for filename in fnmatch.filter(filenames, '*.ts'): @@ -56,9 +56,9 @@ def run(self, callback, errback): if yesterday_begin <= record_end <= yesterday_end: if os.path.getsize(record_path) < 10000000: # 10MB broken_records.append(record_path) - + if broken_records: - callback( SUBJECT, BODY % "\n\n" + "\n".join( broken_records ) ) + callback(SUBJECT, BODY % "\n\n" + "\n".join(broken_records)) else: callback() diff --git a/src/Controller/CrashLog.py b/src/Controller/CrashLog.py index 8add322..2778eb0 100644 --- a/src/Controller/CrashLog.py +++ b/src/Controller/CrashLog.py @@ -31,20 +31,20 @@ CRASHLOG_DIR = '/media/hdd' SUBJECT = _("Found CrashLog(s)") -BODY = _("Crashlog(s) are attached") +BODY = _("Crashlog(s) are attached") class CrashLog(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) self.crashlogs = [] # Default configuration - self.setOption( 'delete_logs', NoSave(ConfigYesNo( default = False )), _("Delete crashlog(s)") ) + self.setOption('delete_logs', NoSave(ConfigYesNo(default=False)), _("Delete crashlog(s)")) def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback @@ -52,12 +52,12 @@ def run(self, callback, errback): # If empty or none is returned, nothing will be sent self.crashlogs = [] text = "Found crashlogs, see attachment(s)\n" - for file in os.listdir( CRASHLOG_DIR ): + for file in os.listdir(CRASHLOG_DIR): if file.startswith("enigma2_crash_") and file.endswith(".log"): - crashlog = os.path.join( CRASHLOG_DIR, file ) + crashlog = os.path.join(CRASHLOG_DIR, file) self.crashlogs.append(crashlog) if self.crashlogs: - callback( SUBJECT, BODY, self.crashlogs ) + callback(SUBJECT, BODY, self.crashlogs) else: callback() @@ -67,18 +67,18 @@ def callback(self): if self.getValue('delete_logs'): # Delete crashlogs for crashlog in self.crashlogs[:]: - if os.path.exists( crashlog ): - os.remove( crashlog ) - self.crashlogs.remove( crashlog ) + if os.path.exists(crashlog): + os.remove(crashlog) + self.crashlogs.remove(crashlog) else: # Rename crashlogs to avoid resending it for crashlog in self.crashlogs[:]: - if os.path.exists( crashlog ): + if os.path.exists(crashlog): # Adapted from autosubmit - instead of .sent we will use .pushed currfilename = str(os.path.basename(crashlog)) newfilename = "/media/hdd/" + currfilename + ".pushed" - os.rename(crashlog,newfilename) - self.crashlogs.remove( crashlog ) + os.rename(crashlog, newfilename) + self.crashlogs.remove(crashlog) def errback(self): # Called after all services has returned, but at least one has failed diff --git a/src/Controller/DeactivatedTimers.py b/src/Controller/DeactivatedTimers.py index 986930d..2b4612b 100644 --- a/src/Controller/DeactivatedTimers.py +++ b/src/Controller/DeactivatedTimers.py @@ -29,73 +29,73 @@ # Constants SUBJECT = _("Found deactivated timer(s)") -BODY = _("Deactivated timer list:\n%s") -TAG = _("DeactivatedTimerPushed") +BODY = _("Deactivated timer list:\n%s") +TAG = _("DeactivatedTimerPushed") class DeactivatedTimers(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) self.timers = [] - + # Default configuration - self.setOption( 'remove_timer', NoSave(ConfigYesNo( default = False )), _("Remove deactivated timer(s)") ) - self.setOption( 'list_similar', NoSave(ConfigYesNo( default = False )), _("List similar timer(s)") ) + self.setOption('remove_timer', NoSave(ConfigYesNo(default=False)), _("Remove deactivated timer(s)")) + self.setOption('list_similar', NoSave(ConfigYesNo(default=False)), _("List similar timer(s)")) def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback # Callback should return with at least one of the parameter: Header, Body, Attachment # If empty or none is returned, nothing will be sent - + self.timers = [] text = "" list_similar = self.getValue('list_similar') - + def timerToString(timer): return str(timer.name) + "\t" \ + strftime(_("%Y.%m.%d %H:%M"), localtime(timer.begin)) + " - " \ + strftime(_("%H:%M"), localtime(timer.end)) + "\t" \ + str(timer.service_ref and timer.service_ref.getServiceName() or "") \ + "\t" + str(timer.tags) - + import NavigationInstance for timer in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers: if timer.justplay: pass - - elif str(timer.service_ref)[0]=="-": + + elif str(timer.service_ref)[0] == "-": pass - + elif TAG in timer.tags: pass - + elif not timer.disabled: pass - + else: text += timerToString(timer) + "\r\n" - + if list_similar: if not timer.eit: text += "\r\n\r\n" + _("Timer has no EIT") + "\r\n\r\n" continue - + text += "\r\n\r\n" + _("Similar:") + "\r\n" - + for t in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers: if not t.disabled and not t.justplay and t.name == timer.name and t.eit != timer.eit: - text += "\t" + timerToString(t) + "\r\n" - + text += "\t" + timerToString(t) + "\r\n" + text += "\r\n" - - self.timers.append( timer ) - + + self.timers.append(timer) + if self.timers and text: - callback( SUBJECT, BODY % text ) + callback(SUBJECT, BODY % text) else: callback() @@ -104,7 +104,7 @@ def callback(self): import NavigationInstance # Called after all services succeded if self.getValue('remove_timer'): - + # Remove deactivated timers for timer in self.timers[:]: if timer in NavigationInstance.instance.RecordTimer.processed_timers: @@ -112,11 +112,11 @@ def callback(self): elif timer in NavigationInstance.instance.RecordTimer.timer_list: NavigationInstance.instance.RecordTimer.timer_list.remove(timer) self.timers.remove(timer) - + # Set tag to avoid resending it for timer in self.timers: if TAG not in timer.tags: - log.debug( "[PS] timer append tag" ) + log.debug("[PS] timer append tag") timer.tags.append(TAG) NavigationInstance.instance.RecordTimer.saveTimer() self.timers = [] diff --git a/src/Controller/FreeSpace.py b/src/Controller/FreeSpace.py index cdd53f4..16258b2 100644 --- a/src/Controller/FreeSpace.py +++ b/src/Controller/FreeSpace.py @@ -31,29 +31,35 @@ # Constants SUBJECT = _("Free space warning") -BODY = _("Free disk space limit has been reached:\n") \ +BODY = _("Free disk space limit has been reached:\n") \ + _("Path: %s\n") \ + _("Limit: %d GB\n") \ + _("Left: %s") #Adapted from: from Components.Harddisk import findMountPoint + + def mountpoint(path): path = os.path.realpath(path) - if os.path.ismount(path) or len(path)==0: return path + if os.path.ismount(path) or len(path) == 0: + return path return mountpoint(os.path.dirname(path)) - + + def getDevicebyMountpoint(hdm, mountpoint): for x in hdm.partitions[:]: if x.mountpoint == mountpoint: return x.device return None + def getHDD(hdm, part): for hdd in hdm.hdd: if hdd.device == part[:3]: return hdd return None + def timerToString(timer): return str(timer.name) + "\t" \ + strftime(_("%Y.%m.%d %H:%M"), localtime(timer.begin)) + " - " \ @@ -63,62 +69,62 @@ def timerToString(timer): class FreeSpace(ControllerBase): - + ForceSingleInstance = False - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - + # Default configuration - self.setOption( 'wakehdd', NoSave(ConfigYesNo( default = False )), _("Allow HDD wake up") ) - self.setOption( 'path', NoSave(ConfigText( default = "/media/hdd/movie", fixed_size = False )), _("Where to check free space") ) - self.setOption( 'limit', NoSave(ConfigNumber( default = 100 )), _("Free space limit in GB") ) - self.setOption( 'listtimer',NoSave(ConfigYesNo( default = False )), _("List upcoming timer") ) - + self.setOption('wakehdd', NoSave(ConfigYesNo(default=False)), _("Allow HDD wake up")) + self.setOption('path', NoSave(ConfigText(default="/media/hdd/movie", fixed_size=False)), _("Where to check free space")) + self.setOption('limit', NoSave(ConfigNumber(default=100)), _("Free space limit in GB")) + self.setOption('listtimer', NoSave(ConfigYesNo(default=False)), _("List upcoming timer")) + def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback # Callback should return with at least one of the parameter: Header, Body, Attachment # If empty or none is returned, nothing will be sent path = self.getValue('path') limit = self.getValue('limit') - + if not self.getValue('wakehdd'): # User specified to avoid HDD wakeup if it is sleeping from Components.Harddisk import harddiskmanager - dev = getDevicebyMountpoint( harddiskmanager, mountpoint(path) ) + dev = getDevicebyMountpoint(harddiskmanager, mountpoint(path)) if dev is not None: - hdd = getHDD( harddiskmanager, dev ) + hdd = getHDD(harddiskmanager, dev) if hdd is not None: if hdd.isSleeping(): # Don't wake up HDD - log.debug( _("[FreeSpace] HDD is idle: ") + str(path) ) + log.debug(_("[FreeSpace] HDD is idle: ") + str(path)) callback() - + # Check free space on path - if os.path.exists( path ): - stat = os.statvfs( path ) - free = ( stat.f_bavail if stat.f_bavail!=0 else stat.f_bfree ) * stat.f_bsize / 1024 / 1024 # MB - if limit > (free/1024): #GB - if free >= 10*1024: #MB - free = "%d GB" %(free/1024) + if os.path.exists(path): + stat = os.statvfs(path) + free = (stat.f_bavail if stat.f_bavail != 0 else stat.f_bfree) * stat.f_bsize / 1024 / 1024 # MB + if limit > (free / 1024): #GB + if free >= 10 * 1024: #MB + free = "%d GB" % (free / 1024) else: - free = "%d MB" %(free) + free = "%d MB" % (free) # Not enough free space text = "" if self.getValue('listtimer'): - text = "\r\n\r\n" - text += _("Next timer:") + text = "\r\n\r\n" + text += _("Next timer:") text += "\r\n" import NavigationInstance now = time() next_day = now + 86400 # Add one day for t in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers: if not t.disabled and not t.justplay and now < t.begin and t.end < next_day: - text += "\t" + timerToString(t) + "\r\n" - - callback( SUBJECT, BODY % (path, limit, free) + text ) + text += "\t" + timerToString(t) + "\r\n" + + callback(SUBJECT, BODY % (path, limit, free) + text) else: # There is enough free space callback() diff --git a/src/Controller/IPKGUpdateNotification.py b/src/Controller/IPKGUpdateNotification.py index 882b9f6..7f21590 100644 --- a/src/Controller/IPKGUpdateNotification.py +++ b/src/Controller/IPKGUpdateNotification.py @@ -33,62 +33,62 @@ # Constants SUBJECT = _("IPKG Update Notification") -BODY = _("There are updates available:\n%s") +BODY = _("There are updates available:\n%s") class IPKGUpdateNotification(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - + # Default configuration - self.setOption( 'selfcheck', NoSave(ConfigYesNo( default = False )), _("Start update check if not done yet") ) + self.setOption('selfcheck', NoSave(ConfigYesNo(default=False)), _("Start update check if not done yet")) def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback # Callback should return with at least one of the parameter: Header, Body, Attachment # If empty or none is returned, nothing will be sent - if iSoftwareTools.lastDownloadDate is not None and iSoftwareTools.lastDownloadDate > ( time() - (24*60*60) ): + if iSoftwareTools.lastDownloadDate is not None and iSoftwareTools.lastDownloadDate > (time() - (24 * 60 * 60)): # Last refresh was within one day return self.buildList(callback, errback) else: - log.debug( "IPKGUpdateNotification run else" ) + log.debug("IPKGUpdateNotification run else") if self.getValue('selfcheck'): # Refresh package list - iSoftwareTools.startSoftwareTools( boundFunction(self.getUpdateInfosCB, callback, errback) ) + iSoftwareTools.startSoftwareTools(boundFunction(self.getUpdateInfosCB, callback, errback)) return callback() - def getUpdateInfosCB(self, callback, errback, retval = None): + def getUpdateInfosCB(self, callback, errback, retval=None): if retval is not None: if retval is True: if iSoftwareTools.available_updates is not 0: # _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.") - log.debug( "Updates available." ) + log.debug("Updates available.") return self.buildList(callback, errback) else: # _("There are no updates available.") - log.debug( "There are no updates available." ) + log.debug("There are no updates available.") return callback() elif retval is False: if iSoftwareTools.lastDownloadDate is None: if iSoftwareTools.NetworkConnectionAvailable: # _("Updatefeed not available.") - log.debug( "Updatefeed not available." ) + log.debug("Updatefeed not available.") return errback(_("Updatefeed not available.")) else: # _("No network connection available.") - log.debug( "No network connection available." ) + log.debug("No network connection available.") return errback(_("No network connection available.")) else: - log.debug( "IPKGUpdateNotification getUpdates" ) + log.debug("IPKGUpdateNotification getUpdates") # Call update iSoftwareTools.lastDownloadDate = time() iSoftwareTools.list_updating = True - iSoftwareTools.getUpdates( boundFunction(self.getUpdateInfosCB, callback, errback) ) + iSoftwareTools.getUpdates(boundFunction(self.getUpdateInfosCB, callback, errback)) return callback() @@ -104,11 +104,10 @@ def buildList(self, callback, errback): if p == packagename: updversion = v break - log.debug( "PushService: " + packagename + " :\t" + instversion + " :\t" + updversion ) + log.debug("PushService: " + packagename + " :\t" + instversion + " :\t" + updversion) if instversion != updversion: updates += packagename + " :\t" + instversion + " :\t" + updversion + "\n" if updates: - callback( SUBJECT, BODY % (updates) ) + callback(SUBJECT, BODY % (updates)) else: callback() - diff --git a/src/Controller/ListDir.py b/src/Controller/ListDir.py index 382a9aa..b85d72f 100644 --- a/src/Controller/ListDir.py +++ b/src/Controller/ListDir.py @@ -15,52 +15,49 @@ # GNU General Public License for more details. # ####################################################################### - + # Config from Components.config import ConfigYesNo, ConfigText, ConfigNumber, NoSave - + # Plugin internal from Plugins.Extensions.PushService.__init__ import _ from Plugins.Extensions.PushService.ControllerBase import ControllerBase - + # Plugin specific import os - - + + # Constants - + SUBJECT = _("List of Files") - - - - + + class ListDir(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - self.movielist= [] - + self.movielist = [] + # Default configuration - self.setOption( 'path', NoSave(ConfigText( default = "/media/hdd/movie/", fixed_size = False )), _("Where to check") ) - self.setOption( 'ext', NoSave(ConfigText( default = ".ts", fixed_size = False )), _("file extension") ) - - + self.setOption('path', NoSave(ConfigText(default="/media/hdd/movie/", fixed_size=False)), _("Where to check")) + self.setOption('ext', NoSave(ConfigText(default=".ts", fixed_size=False)), _("file extension")) + def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback # Callback should return with at least one of the parameter: Header, body (List of Files) # If empty or none is returned, nothing will be sent path = self.getValue('path') - ext = self.getValue('ext') + ext = self.getValue('ext') movielist = [] - for file in os.listdir( path ): - if file.endswith( ext ): + for file in os.listdir(path): + if file.endswith(ext): movielist.append(file) body = "The following files were found: \n" + "\n".join(movielist) - + if movielist: - callback( SUBJECT, body ) + callback(SUBJECT, body) else: callback() diff --git a/src/Controller/MissingTimers.py b/src/Controller/MissingTimers.py index cbcf32f..3d60773 100644 --- a/src/Controller/MissingTimers.py +++ b/src/Controller/MissingTimers.py @@ -30,13 +30,13 @@ # Constants SUBJECT = _("Missing timer") -BODY = _("There are no timer for tomorrow - %s") +BODY = _("There are no timer for tomorrow - %s") class MissingTimers(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) @@ -46,18 +46,18 @@ def run(self, callback, errback): # Callback should return with at least one of the parameter: Header, Body, Attachment # If empty or none is returned, nothing will be sent timers = 0 - tomorrow_begin = mktime( ( date.today() + timedelta(days=1) ).timetuple() ) - tomorrow_end = tomorrow_begin + 24*60*60 - + tomorrow_begin = mktime((date.today() + timedelta(days=1)).timetuple()) + tomorrow_end = tomorrow_begin + 24 * 60 * 60 + for timer in NavigationInstance.instance.RecordTimer.timer_list: - if not timer.disabled and str(timer.service_ref)[0]!="-": + if not timer.disabled and str(timer.service_ref)[0] != "-": timer_begin = timer.begin if tomorrow_begin <= timer_begin <= tomorrow_end: timers += 1 break - + if timers == 0: - callback( SUBJECT, BODY % strftime(_("%Y.%m.%d"), localtime(tomorrow_begin))) + callback(SUBJECT, BODY % strftime(_("%Y.%m.%d"), localtime(tomorrow_begin))) else: callback() diff --git a/src/Controller/OPKGUpdateNotification.py b/src/Controller/OPKGUpdateNotification.py index d922e08..cebb45d 100644 --- a/src/Controller/OPKGUpdateNotification.py +++ b/src/Controller/OPKGUpdateNotification.py @@ -33,20 +33,20 @@ # Constants SUBJECT = _("OPKG Update Notification") -BODY = _("There are updates available:\n%s") +BODY = _("There are updates available:\n%s") class OPKGUpdateNotification(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - + # Default configuration - self.setOption( 'selfcheck', NoSave(ConfigYesNo( default = False )), _("Start update check if not done yet") ) - + self.setOption('selfcheck', NoSave(ConfigYesNo(default=False)), _("Start update check if not done yet")) + self.data = "" self.container = eConsoleAppContainer() try: @@ -75,23 +75,23 @@ def opkgupgradable(self): self.container.execute("opkg list-upgradable") def opkgupgradableFinished(self, retval=None): - + try: - log.debug( "PushService retval: ",str(retval) ) + log.debug("PushService retval: ", str(retval)) except: pass try: - log.debug( "PushService self.data: ",str(self.data) ) + log.debug("PushService self.data: ", str(self.data)) except: pass - + updates = "" excepts = "" - + if self.data: try: for line in self.data.split("\n"): - log.debug( "PushService opkg upgradable data: ",line ) + log.debug("PushService opkg upgradable data: ", line) if line.startswith("Inflating"): continue if line.startswith("Updated"): @@ -121,16 +121,15 @@ def opkgupgradableFinished(self, retval=None): updates += line + "\r\n" except Exception, e: excepts += "\r\n\r\nException:\r\n" + str(e) - + if excepts: - log.exception( excepts ) - + log.exception(excepts) + if updates: #callback( SUBJECT, BODY % (updates) ) - + #TODO Problem test run won't get the message # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, BODY % (updates)) - diff --git a/src/Controller/RecordNotification.py b/src/Controller/RecordNotification.py index a6ff169..575e567 100644 --- a/src/Controller/RecordNotification.py +++ b/src/Controller/RecordNotification.py @@ -34,32 +34,32 @@ class RecordNotification(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - + self.forceBindRecordTimer = eTimer() try: self.forceBindRecordTimer_conn = self.forceBindRecordTimer.timeout.connect(self.begin) except: self.forceBindRecordTimer.callback.append(self.begin) - + # Default configuration - self.setOption( 'send_on_start', NoSave(ConfigYesNo( default = False )), _("Send notification on record start") ) - self.setOption( 'send_on_end', NoSave(ConfigYesNo( default = True )), _("Send notification on record end") ) - self.setOption( 'include_description', NoSave(ConfigYesNo( default = False )), _("Include timer description") ) + self.setOption('send_on_start', NoSave(ConfigYesNo(default=False)), _("Send notification on record start")) + self.setOption('send_on_end', NoSave(ConfigYesNo(default=True)), _("Send notification on record end")) + self.setOption('include_description', NoSave(ConfigYesNo(default=False)), _("Include timer description")) #TODO option to send free space def begin(self): # Is called after starting PushService - + if self.getValue('send_on_start') or self.getValue('send_on_end'): if NavigationInstance.instance: if self.onRecordEvent not in NavigationInstance.instance.RecordTimer.on_state_change: - log.debug( "append" ) + log.debug("append") # Append callback function NavigationInstance.instance.RecordTimer.on_state_change.append(self.onRecordEvent) else: @@ -85,16 +85,16 @@ def run(self, callback, errback): def onRecordEvent(self, timer): text = "" include_description = self.getValue('include_description') - + if timer.justplay: pass - - elif str(timer.service_ref)[0]=="-": + + elif str(timer.service_ref)[0] == "-": pass - + elif timer.state == timer.StatePrepared: pass - + elif timer.state == timer.StateRunning: timer.ps_running = True if self.getValue('send_on_start'): @@ -106,7 +106,7 @@ def onRecordEvent(self, timer): if include_description: text += "\n\n" + str(timer.description) del timer - + # Finished repeating timer will report the state StateEnded+1 or StateWaiting elif timer.state == timer.StateEnded or timer.repeated and timer.state == timer.StateWaiting: if hasattr(timer, "ps_running") and timer.ps_running: @@ -120,11 +120,10 @@ def onRecordEvent(self, timer): if include_description: text += "\n\n" + str(timer.description) del timer - + if text: #TODO Problem test run won't get the message # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, text) - diff --git a/src/Controller/RecordSummary.py b/src/Controller/RecordSummary.py index 47636f5..55ba5e6 100644 --- a/src/Controller/RecordSummary.py +++ b/src/Controller/RecordSummary.py @@ -30,22 +30,22 @@ # Constants SUBJECT = _("Record Summary") -BODY = _("Finished record list:\n%s") -TAG = _("FinishedTimerPushed") +BODY = _("Finished record list:\n%s") +TAG = _("FinishedTimerPushed") class RecordSummary(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) self.timers = [] - + # Default configuration - self.setOption( 'remove_timer', NoSave(ConfigYesNo( default = False )), _("Remove finished timer(s)") ) - self.setOption( 'include_description', NoSave(ConfigYesNo( default = False )), _("Include timer description") ) + self.setOption('remove_timer', NoSave(ConfigYesNo(default=False)), _("Remove finished timer(s)")) + self.setOption('include_description', NoSave(ConfigYesNo(default=False)), _("Include timer description")) def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback @@ -56,16 +56,16 @@ def run(self, callback, errback): for timer in NavigationInstance.instance.RecordTimer.processed_timers: if timer.justplay: pass - - elif str(timer.service_ref)[0]=="-": + + elif str(timer.service_ref)[0] == "-": pass - + elif TAG in timer.tags: pass - + elif timer.disabled: pass - + else: text += str(timer.name) + "\t" \ + strftime(_("%Y.%m.%d %H:%M"), localtime(timer.begin)) + " - " \ @@ -74,9 +74,9 @@ def run(self, callback, errback): + "\n" if self.getValue('include_description'): text += str(timer.description) + "\n\n" - self.timers.append( timer ) + self.timers.append(timer) if self.timers and text: - callback( SUBJECT, BODY % text ) + callback(SUBJECT, BODY % text) else: callback() diff --git a/src/Controller/SendLog.py b/src/Controller/SendLog.py index 119cfe7..eb2ad07 100644 --- a/src/Controller/SendLog.py +++ b/src/Controller/SendLog.py @@ -30,25 +30,25 @@ # Constants SUBJECT = _("Found Log(s)") -BODY = _("Log(s) are attached") +BODY = _("Log(s) are attached") class SendLog(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) self.logfiles = [] # Default configuration - self.setOption( 'path', NoSave(ConfigText( default = "/media/hdd/", fixed_size = False )), _("Path to check") ) - self.setOption( 'file_pattern', NoSave(ConfigText( default = "*.log", fixed_size = False )), _("Filename pattern (No RegExp)") ) - self.setOption( 'content_pattern', NoSave(ConfigText( default = ".*", fixed_size = False )), _("Content pattern (RegExp)") ) - self.setOption( 'scan_subs', NoSave(ConfigYesNo( default = False )), _("Scan subfolders") ) - self.setOption( 'rename_logs', NoSave(ConfigYesNo( default = False )), _("Rename log(s)") ) - self.setOption( 'delete_logs', NoSave(ConfigYesNo( default = False )), _("Delete log(s)") ) + self.setOption('path', NoSave(ConfigText(default="/media/hdd/", fixed_size=False)), _("Path to check")) + self.setOption('file_pattern', NoSave(ConfigText(default="*.log", fixed_size=False)), _("Filename pattern (No RegExp)")) + self.setOption('content_pattern', NoSave(ConfigText(default=".*", fixed_size=False)), _("Content pattern (RegExp)")) + self.setOption('scan_subs', NoSave(ConfigYesNo(default=False)), _("Scan subfolders")) + self.setOption('rename_logs', NoSave(ConfigYesNo(default=False)), _("Rename log(s)")) + self.setOption('delete_logs', NoSave(ConfigYesNo(default=False)), _("Delete log(s)")) def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback @@ -63,32 +63,32 @@ def run(self, callback, errback): if self.getValue('scan_subs'): for root, dirnames, filenames in os.walk(path): for filename in fnmatch.filter(filenames, file_pattern): - logfile = os.path.join( root, filename ) - if( content_pattern == ".*" ): - self.logfiles.append( logfile ) + logfile = os.path.join(root, filename) + if(content_pattern == ".*"): + self.logfiles.append(logfile) else: - infile = open(logfile,"r") + infile = open(logfile, "r") for line in infile: if prog.match(line): - self.logfiles.append( logfile ) + self.logfiles.append(logfile) break infile.close() else: - filenames = os.listdir( path ) + filenames = os.listdir(path) for filename in fnmatch.filter(filenames, file_pattern): - logfile = os.path.join( path, filename ) - if( content_pattern == ".*" ): - self.logfiles.append( logfile ) + logfile = os.path.join(path, filename) + if(content_pattern == ".*"): + self.logfiles.append(logfile) else: - infile = open(logfile,"r") + infile = open(logfile, "r") for line in infile: if prog.match(line): - self.logfiles.append( logfile ) + self.logfiles.append(logfile) break infile.close() - + if self.logfiles: - callback( SUBJECT, BODY, self.logfiles ) + callback(SUBJECT, BODY, self.logfiles) else: callback() @@ -98,18 +98,18 @@ def callback(self): if self.getValue('delete_logs'): # Delete logfiles for logfile in self.logfiles[:]: - if os.path.exists( logfile ): - os.remove( logfile ) - self.logfiles.remove( logfile ) + if os.path.exists(logfile): + os.remove(logfile) + self.logfiles.remove(logfile) elif self.getValue('rename_logs'): # Rename logfiles to avoid resending it for logfile in self.logfiles[:]: - if os.path.exists( logfile ): + if os.path.exists(logfile): # Adapted from autosubmit - instead of .sent we will use .pushed currfilename = str(os.path.basename(logfile)) newfilename = "/media/hdd/" + currfilename + ".pushed" - os.rename(logfile,newfilename) - self.logfiles.remove( logfile ) + os.rename(logfile, newfilename) + self.logfiles.remove(logfile) def errback(self): # Called after all services has returned, but at least one has failed diff --git a/src/Controller/StandbyNotification.py b/src/Controller/StandbyNotification.py index 4f4ab1c..95a419d 100644 --- a/src/Controller/StandbyNotification.py +++ b/src/Controller/StandbyNotification.py @@ -31,68 +31,68 @@ class StandbyNotification(ControllerBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ControllerBase.__init__(self) - + # Default configuration - self.setOption( 'send_after_bootup', NoSave(ConfigYesNo( default = False )), _("Send notification after bootup") ) - self.setOption( 'send_before_shutdown', NoSave(ConfigYesNo( default = False )), _("Send notification before shutdown") ) - self.setOption( 'send_before_standby', NoSave(ConfigYesNo( default = True )), _("Send notification before standby") ) - self.setOption( 'send_after_standby', NoSave(ConfigYesNo( default = True )), _("Send notification after standby") ) - + self.setOption('send_after_bootup', NoSave(ConfigYesNo(default=False)), _("Send notification after bootup")) + self.setOption('send_before_shutdown', NoSave(ConfigYesNo(default=False)), _("Send notification before shutdown")) + self.setOption('send_before_standby', NoSave(ConfigYesNo(default=True)), _("Send notification before standby")) + self.setOption('send_after_standby', NoSave(ConfigYesNo(default=True)), _("Send notification after standby")) + def leaveStandby(self, dummy=None): #log.debug( "leave standby" ) - + if self.getValue('send_after_standby'): text = _("Enigma2 wakeup after Standby") - + # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, text) - + def standbyCountChanged(self, configElement=None): #log.debug( "enter standby num", configElement.value ) from Screens.Standby import inStandby inStandby.onClose.append(self.leaveStandby) - + if self.getValue('send_before_standby'): text = _("Enigma2 going into Standby") - + # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, text) - + def begin(self): # Is called after starting PushService - + if self.getValue('send_after_bootup'): text = _("Enigma2 booted") - + # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, text) - + from Components.config import config - config.misc.standbyCounter.addNotifier(self.standbyCountChanged, initial_call = False) + config.misc.standbyCounter.addNotifier(self.standbyCountChanged, initial_call=False) def end(self): # Is called after stopping PushSerive - + if self.getValue('send_before_shutdown'): text = _("Enigma2 shutdown initiated") - + # Push mail from Plugins.Extensions.PushService.plugin import gPushService if gPushService: gPushService.push(self, SUBJECT, text) - + def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback # Callback should return with at least one of the parameter: Header, Body, Attachment diff --git a/src/ControllerBase.py b/src/ControllerBase.py index fb9f9fb..a1bf919 100644 --- a/src/ControllerBase.py +++ b/src/ControllerBase.py @@ -24,18 +24,17 @@ class ControllerBase(ModuleBase): # You only have to overwrite the functions You need # If You don't have to save something, You don't need getOptions / setOptions - + UniqueCounter = 0 - + ForceSingleInstance = True - + def __init__(self): ModuleBase.__init__(self) # Is called on instance creation ControllerBase.UniqueCounter += 1 self.uniqueid = ControllerBase.UniqueCounter - ################################################ # Base class functions @classmethod @@ -46,14 +45,14 @@ def forceSingle(cls): def resetUniqueID(): ControllerBase.UniqueCounter = 0 - ################################################ # Functions to be implemented in the plugin + def run(self, callback, errback): # At the end a plugin has to call one of the functions: callback or errback # Callback should return with at least one of the parameter: Header, Body, Attachment # If empty or none is returned, nothing will be sent - errback( "Not implemented: " + self.getName() + ".run()") + errback("Not implemented: " + self.getName() + ".run()") # Callback functions def callback(self): diff --git a/src/Logger.py b/src/Logger.py index 05ebc7e..b44ee83 100644 --- a/src/Logger.py +++ b/src/Logger.py @@ -21,7 +21,9 @@ import logging -import os, sys, traceback +import os +import sys +import traceback from Components.config import config @@ -37,15 +39,15 @@ class Logger(object): def __init__(self): self.instance = logging.getLogger("pushservice") self.instance.setLevel(logging.DEBUG) - + self.reinit() - + def reinit(self): - self.instance.handlers = [] - + self.instance.handlers = [] + if not hasattr(config, "pushservice"): return - + if config.pushservice.log_shell.value: shandler = logging.StreamHandler(sys.stdout) shandler.setLevel(logging.DEBUG) @@ -55,7 +57,7 @@ def reinit(self): self.instance.addHandler(shandler) self.instance.setLevel(logging.DEBUG) - + if config.pushservice.log_write.value: fhandler = logging.FileHandler(config.pushservice.log_file.value) fhandler.setLevel(logging.DEBUG) @@ -71,52 +73,52 @@ def shutdown(self): self.instance.shutdown() def info(self, *args): - strargs = " ".join( [ str(arg) for arg in args ] ) - + strargs = " ".join([str(arg) for arg in args]) + if self.instance: self.instance.info(strargs) - + elif config.pushservice.log_shell.value: print strargs def debug(self, *args): - strargs = " ".join( [ str(arg) for arg in args ] ) - + strargs = " ".join([str(arg) for arg in args]) + if self.instance: self.instance.debug(strargs) - + elif config.pushservice.log_shell.value: print strargs - + if sys.exc_info()[0]: - self.instance.debug( str(sys.exc_info()[0]) ) - self.instance.debug( str(traceback.format_exc()) ) + self.instance.debug(str(sys.exc_info()[0])) + self.instance.debug(str(traceback.format_exc())) sys.exc_clear() def warning(self, *args): - strargs = " ".join( [ str(arg) for arg in args ] ) - + strargs = " ".join([str(arg) for arg in args]) + if self.instance: self.instance.warning(strargs) - + elif config.pushservice.log_shell.value: print strargs - + if int(config.pushservice.popups_warning_timeout.value) != 0: if currentThread().getName() == 'MainThread': AddPopup( strargs, MessageBox.TYPE_WARNING, int(config.pushservice.popups_warning_timeout.value), - 'PS_PopUp_ID_Warning_'+strargs + 'PS_PopUp_ID_Warning_' + strargs ) def error(self, *args): - strargs = " ".join( [ str(arg) for arg in args ] ) - + strargs = " ".join([str(arg) for arg in args]) + if self.instance: self.instance.error(strargs) - + elif config.pushservice.log_shell.value: print strargs @@ -126,35 +128,36 @@ def error(self, *args): strargs, MessageBox.TYPE_ERROR, int(config.pushservice.popups_error_timeout.value), - 'PS_PopUp_ID_Error_'+strargs + 'PS_PopUp_ID_Error_' + strargs ) - + def exception(self, *args): - strargs = " ".join( [ str(arg) for arg in args ] ) - + strargs = " ".join([str(arg) for arg in args]) + if self.instance: self.instance.exception(strargs) - + elif config.pushservice.log_shell.value: print strargs - + if int(config.pushservice.popups_error_timeout.value) != 0: if currentThread().getName() == 'MainThread': AddPopup( strargs, MessageBox.TYPE_ERROR, int(config.pushservice.popups_error_timeout.value), - 'PS_PopUp_ID_Exception_'+strargs + 'PS_PopUp_ID_Exception_' + strargs ) - - import os, sys, traceback + + import os + import sys + import traceback if sys.exc_info()[0]: #exc_type, exc_value, exc_traceback = sys.exc_info() #traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stdout) - self.debug( str(sys.exc_info()[0]) ) - self.debug( str(traceback.format_exc()) ) + self.debug(str(sys.exc_info()[0])) + self.debug(str(traceback.format_exc())) sys.exc_clear() log = Logger() - diff --git a/src/ModuleBase.py b/src/ModuleBase.py index 385f1cf..954f716 100644 --- a/src/ModuleBase.py +++ b/src/ModuleBase.py @@ -33,17 +33,16 @@ class ModuleBase(object): def __init__(self): # Is called on instance creation - + # Default configuration - self.enable = NoSave(ConfigYesNo( default = False )) - + self.enable = NoSave(ConfigYesNo(default=False)) + self.options = OrderedDict() - + # Build a list of key-value string tuples # [ (key, value, description, config element) , ] #self.options['enabled'] = ConfigYesNo( default = False ) - ################################################ # Base classmethod functions @classmethod @@ -51,9 +50,9 @@ def getClass(cls): # Return the Class return cls.__name__ - ################################################ # Base functions + def getName(self): # Return the Class Name return self.__class__.__name__ @@ -77,7 +76,7 @@ def getOption(self, key): return None def setOption(self, key, option, description): - self.options[key] = ( option, description ) + self.options[key] = (option, description) def setOptions(self, options): # Parse a list of key-value string tuples @@ -93,8 +92,8 @@ def setOptions(self, options): elif type(default) is int: self.setValue(key, int(value)) except: - log.debug( ("PushService Module %s:\n") % ( self.getName() ) ) - log.debug( ("Skipping config option:") + str(key) + " " + str(value) ) + log.debug(("PushService Module %s:\n") % (self.getName())) + log.debug(("Skipping config option:") + str(key) + " " + str(value)) continue def getUniqueID(self): @@ -113,14 +112,14 @@ def getStringEnable(self): return str(self.enable.value) def getStringOptions(self): - return [ ( str(key), str(option.value), str(description) ) for ( key, ( option, description ) ) in self.options.items() ] + return [(str(key), str(option.value), str(description)) for (key, (option, description)) in self.options.items()] def getConfigOptions(self): - return [ ( key, option, description) for ( key, ( option, description ) ) in self.options.items() ] - + return [(key, option, description) for (key, (option, description)) in self.options.items()] ################################################ # Functions to be implemented in the plugin + def begin(self): # Is called after starting PushSerive pass diff --git a/src/Modules.py b/src/Modules.py index eec152c..ad575d1 100644 --- a/src/Modules.py +++ b/src/Modules.py @@ -16,10 +16,13 @@ # ####################################################################### -import os, sys, traceback +import os +import sys +import traceback # Plugin framework -import imp, inspect +import imp +import inspect # Plugin internal from . import _ @@ -38,61 +41,62 @@ def __init__(self): # Module functions def loadModules(self, path, base): modules = {} - + if not os.path.exists(path): return - + # Import all subfolders to allow relative imports for root, dirs, files in os.walk(path): if root not in sys.path: sys.path.append(root) - + # Import PushService modules files = [fname[:-3] for fname in os.listdir(path) if fname.endswith(".py")] for name in files: module = None - + if name == "__init__": continue - + try: fp, pathname, description = imp.find_module(name, [path]) except Exception, e: - log.exception( ("PushService Find module exception: ") + str(e) ) + log.exception(("PushService Find module exception: ") + str(e)) fp = None - + if not fp: - log.debug( ("PushService No module found: ") + str(name) ) + log.debug(("PushService No module found: ") + str(name)) continue - + try: - module = imp.load_module( name, fp, pathname, description) + module = imp.load_module(name, fp, pathname, description) except Exception, e: - log.exception( ("PushService Load exception: ") + str(e) ) + log.exception(("PushService Load exception: ") + str(e)) finally: # Since we may exit via an exception, close fp explicitly. - if fp: fp.close() - + if fp: + fp.close() + if not module: - log.debug( ("PushService No module available: ") + str(name) ) + log.debug(("PushService No module available: ") + str(name)) continue - + # Continue only if the attribute is available if not hasattr(module, name): - log.debug( ("PushService Warning attribute not available: ") + str(name) ) + log.debug(("PushService Warning attribute not available: ") + str(name)) continue - + # Continue only if attr is a class attr = getattr(module, name) if not inspect.isclass(attr): - log.debug( ("PushService Warning no class definition: ") + str(name) ) + log.debug(("PushService Warning no class definition: ") + str(name)) continue - + # Continue only if the class is a subclass of the corresponding base class - if not issubclass( attr, base): - log.debug( ("PushService Warning no subclass of base: ") + str(name) ) + if not issubclass(attr, base): + log.debug(("PushService Warning no subclass of base: ") + str(name)) continue - + # Add module to the module list modules[name] = attr return modules @@ -103,7 +107,7 @@ def instantiateModule(self, module): try: return module() except Exception, e: - log.exception( ("PushService Instantiate exception: ") + str(module) + "\n" + str(e) ) + log.exception(("PushService Instantiate exception: ") + str(module) + "\n" + str(e)) else: - log.debug( ("PushService Module is not callable") ) + log.debug(("PushService Module is not callable")) return None diff --git a/src/OrderedDict.py b/src/OrderedDict.py index d817797..bf49eb4 100644 --- a/src/OrderedDict.py +++ b/src/OrderedDict.py @@ -237,7 +237,7 @@ def __eq__(self, other): ''' if isinstance(other, OrderedDict): - return len(self)==len(other) and self.items() == other.items() + return len(self) == len(other) and self.items() == other.items() return dict.__eq__(self, other) def __ne__(self, other): diff --git a/src/PushService.py b/src/PushService.py index 90ddd39..b3cc600 100644 --- a/src/PushService.py +++ b/src/PushService.py @@ -17,7 +17,8 @@ ####################################################################### import os -import sys, traceback +import sys +import traceback from time import localtime from Components.config import config @@ -42,68 +43,70 @@ class PushService(PushServiceBase): def __init__(self): PushServiceBase.__init__(self) - + self.state = PSBOOT if config.pushservice.runonboot.value else PSFIRST - + self.timer = eTimer() try: self.timer_conn = self.timer.timeout.connect(self.do) except: self.timer.callback.append(self.do) - + # Read XML file, parse it and instantiate configured plugins self.load() - - #TODO Run in a new thread + #TODO Run in a new thread ###################################### # Statemachine and timer + def start(self): log.reinit() - - log.info( "PushService start" ) + + log.info("PushService start") self.stopTimer() - + self.begin() self.next() def stop(self): - log.debug( "PushService stop" ) + log.debug("PushService stop") self.stopTimer() - + self.end() self.state = PSFIRST - def next(self, state = None): - if state: self.state = state - log.debug( "PushService next", self.state ) - + def next(self, state=None): + if state: + self.state = state + log.debug("PushService next", self.state) + if self.state == PSBOOT: - self.startTimer( int(config.pushservice.bootdelay.value), PSBOOTRUN ) - + self.startTimer(int(config.pushservice.bootdelay.value), PSBOOTRUN) + elif self.state == PSBOOTRUN \ or self.state == PSFIRST: cltime = config.pushservice.time.value lotime = localtime() - ltime = lotime[3]*60 + lotime[4] - ctime = cltime[0]*60 + cltime[1] + ltime = lotime[3] * 60 + lotime[4] + ctime = cltime[0] * 60 + cltime[1] seconds = 60 * abs(ctime - ltime) - self.startTimer( seconds, PSFIRSTRUN ) - + self.startTimer(seconds, PSFIRSTRUN) + elif self.state == PSFIRSTRUN \ or self.state == PSCYCLE: period = int(config.pushservice.period.value) if period > 0: - self.startTimer( period*60*60, PSCYCLE ) + self.startTimer(period * 60 * 60, PSCYCLE) def do(self): self.run() self.next() def startTimer(self, seconds, state=None): - if state: self.state = state - self.timer.startLongTimer( seconds ) + if state: + self.state = state + self.timer.startLongTimer(seconds) def stopTimer(self): if self.timer.isActive(): diff --git a/src/PushServiceBase.py b/src/PushServiceBase.py index 25cb076..103b8ca 100644 --- a/src/PushServiceBase.py +++ b/src/PushServiceBase.py @@ -16,7 +16,9 @@ # ####################################################################### -import os, sys, traceback +import os +import sys +import traceback from time import localtime, strftime # Config @@ -44,8 +46,8 @@ CONTROLLER = "Controller" OPTION = "Option" -SERVICE_PATH = os.path.join( resolveFilename(SCOPE_PLUGINS), "Extensions/PushService/Services/" ) -CONTROLLER_PATH = os.path.join( resolveFilename(SCOPE_PLUGINS), "Extensions/PushService/Controller/" ) +SERVICE_PATH = os.path.join(resolveFilename(SCOPE_PLUGINS), "Extensions/PushService/Services/") +CONTROLLER_PATH = os.path.join(resolveFilename(SCOPE_PLUGINS), "Extensions/PushService/Controller/") class PushServiceBase(Modules, ConfigFile): @@ -53,20 +55,20 @@ class PushServiceBase(Modules, ConfigFile): def __init__(self, path=""): Modules.__init__(self) ConfigFile.__init__(self) - + self.services = [] self.controllers = [] - + self.pushcallbacks = {} self.pusherrbacks = {} - + # Read module files from subfolders self.servicemodules = self.loadModules(SERVICE_PATH, ServiceBase) self.controllermodules = self.loadModules(CONTROLLER_PATH, ControllerBase) - ###################################### # Setter / Getter + def getServices(self): return self.services or [] @@ -79,33 +81,33 @@ def getService(self, idx): def getAvlServices(self): slist = [] if self.servicemodules: - serviceclasses = [ service.getClass() for service in self.services] if self.services else [] + serviceclasses = [service.getClass() for service in self.services] if self.services else [] for name, module in self.servicemodules.iteritems(): if module.forceSingle(): # We have to check if there is already a plugin instance if name in serviceclasses: # A service instance already exists continue - slist.append( (name, module) ) + slist.append((name, module)) slist.sort() return slist def getServiceInstances(self): - return [( service.getNameId(), service ) for service in self.getServices() ] + return [(service.getNameId(), service) for service in self.getServices()] def addService(self, module): id = None - service = module and self.instantiateModule( module ) + service = module and self.instantiateModule(module) if service: service.setEnable(True) - self.services.append( service ) - self.services.sort( key=lambda x: ( x.getUniqueID() ) ) + self.services.append(service) + self.services.sort(key=lambda x: (x.getUniqueID())) id = service.getUniqueID() return id def removeService(self, service): if service in self.services: - self.services.remove( service ) + self.services.remove(service) def getControllers(self): return self.controllers or [] @@ -119,37 +121,37 @@ def getController(self, idx): def getAvlControllers(self): plist = [] if self.controllermodules: - controllerclasses = [ controller.getClass() for controller in self.controllers] if self.controllers else [] + controllerclasses = [controller.getClass() for controller in self.controllers] if self.controllers else [] for name, module in self.controllermodules.iteritems(): if module.forceSingle(): # We have to check if there is already a controller instance if name in controllerclasses: # A controller instance already exists continue - plist.append( (name, module) ) + plist.append((name, module)) plist.sort() return plist def getControllerInstances(self): - return [( controller.getNameId(), controller ) for controller in self.getControllers() ] + return [(controller.getNameId(), controller) for controller in self.getControllers()] def addController(self, module): id = None - controller = module and self.instantiateModule( module ) + controller = module and self.instantiateModule(module) if controller: controller.setEnable(True) - self.controllers.append( controller ) - self.controllers.sort( key=lambda x: ( x.getUniqueID() ) ) + self.controllers.append(controller) + self.controllers.sort(key=lambda x: (x.getUniqueID())) id = controller.getUniqueID() return id def removeController(self, controller): if controller in self.controllers: - self.controllers.remove( controller ) - + self.controllers.remove(controller) ###################################### # Config + def copyto(self, destination): destination.services = self.services destination.controllers = self.controllers @@ -168,11 +170,12 @@ def load(self): if root: services = [] controllers = [] - + # Reset the unique id counters ServiceBase.resetUniqueID() ControllerBase.resetUniqueID() # Parse Config + def parse(root, typ, modules): instances = [] if root: @@ -184,7 +187,7 @@ def parse(root, typ, modules): instance = self.instantiateModule(module) if instance: instance.setEnable(eval(enable)) - + # Set instance options options = [] for option in element.findall(OPTION): @@ -192,16 +195,16 @@ def parse(root, typ, modules): value = option.text if key and value: options.append((key, value)) - + if options: instance.setOptions(options) - + # Append to active controller list instances.append(instance) return instances - services = parse( root, SERVICE, self.servicemodules ) - controllers = parse( root, CONTROLLER, self.controllermodules ) - + services = parse(root, SERVICE, self.servicemodules) + controllers = parse(root, CONTROLLER, self.controllermodules) + self.services = services self.controllers = controllers else: @@ -213,35 +216,35 @@ def save(self): root = None services = self.services controllers = self.controllers - + # Build Header from plugin import NAME, VERSION root = Element(NAME) root.set('version', VERSION) root.append(Comment(_("Don't edit this manually unless you really know what you are doing"))) - + # Build Body def build(root, instances, typ): for instance in instances: # Add module - element = SubElement( root, typ, name = stringToXML(instance.getName()), enable = stringToXML(instance.getStringEnable()) ) + element = SubElement(root, typ, name=stringToXML(instance.getName()), enable=stringToXML(instance.getStringEnable())) # Add options options = instance.getStringOptions() if options: for key, value, description in options: - SubElement( element, OPTION, key = stringToXML(key) ).text = stringToXML(value) + SubElement(element, OPTION, key=stringToXML(key)).text = stringToXML(value) return root - + if services: - root = build( root, services, SERVICE) + root = build(root, services, SERVICE) if controllers: - root = build( root, controllers, CONTROLLER) - - self.writeXML( root ) + root = build(root, controllers, CONTROLLER) + self.writeXML(root) ###################################### # Controller handling + def begin(self): # Loop over all Services for service in self.getServices(): @@ -263,32 +266,32 @@ def end(self): controller.end() def run(self): - log.debug( ("PushService started: ") + strftime( _("%d.%m.%Y %H:%M"), localtime() ) ) - + log.debug(("PushService started: ") + strftime(_("%d.%m.%Y %H:%M"), localtime())) + controllers = self.controllers self.pushcallbacks = {} self.pusherrbacks = {} - + # Loop over all Controllers if controllers: for controller in controllers: if controller.getEnable(): - log.debug( ("PushService running: ") + str( controller.getName() ) ) - + log.debug(("PushService running: ") + str(controller.getName())) + try: # Run controller ret = controller.run( boundFunction(self.runcallback, controller), - boundFunction(self.runerrback, controller) ) + boundFunction(self.runerrback, controller)) except Exception, e: - log.exception( "PushService controller run() exception" , str(e) ) + log.exception("PushService controller run() exception", str(e)) exc_type, exc_value, exc_traceback = sys.exc_info() self.runerrback(controller, exc_type, exc_value, exc_traceback) def runcallback(self, controller, *args): services = self.services subject, body, attachments = "", "", [] - + # Parse return value(s) if args: if len(args) == 3: @@ -299,13 +302,13 @@ def runcallback(self, controller, *args): else: # Only header returned subject = args - + if subject: # Push notification self.push(controller, subject, body, attachments) def runerrback(self, controller, *args): - log.debug( ("controller %s returned error(s)") % controller.getName() ) + log.debug(("controller %s returned error(s)") % controller.getName()) text = "" for arg in args: if isinstance(arg, Exception): @@ -315,12 +318,12 @@ def runerrback(self, controller, *args): text += str(arg) + "\n" elif arg: text += str(arg) + "\n" - log.debug( text ) + log.debug(text) if config.pushservice.push_errors.value: self.push(controller, _("PushService controller run() exception"), text, []) def push(self, controller, subject, text="", attachments=[]): - log.debug( "[PS] push" ) + log.debug("[PS] push") services = self.services if not services: # Fallback to PopUp @@ -336,14 +339,14 @@ def push(self, controller, subject, text="", attachments=[]): boundFunction(self.pushcallback, service, controller), boundFunction(self.pusherrback, service, controller), controller.getName(), - subject, text, attachments ) + subject, text, attachments) except Exception, e: - log.debug( "PushService Service push() exception") + log.debug("PushService Service push() exception") exc_type, exc_value, exc_traceback = sys.exc_info() self.pusherrback(service, controller, exc_type, exc_value, exc_traceback) def pushcallback(self, service, controller, *args): - log.debug( "[PS] pushcallback" ) + log.debug("[PS] pushcallback") key = (service, controller) if key not in self.pushcallbacks: self.pushcallbacks[key] = list(args) @@ -352,13 +355,13 @@ def pushcallback(self, service, controller, *args): self.pushcheckbacks(key) def pusherrback(self, service, controller, *args): - log.debug( "[PS] pusherrback" ) - log.debug( ("Service %s returned error(s)") % service.getName() ) + log.debug("[PS] pusherrback") + log.debug(("Service %s returned error(s)") % service.getName()) for arg in args: if isinstance(arg, Exception): - log.debug( str(arg.type), str(arg.value) ) + log.debug(str(arg.type), str(arg.value)) elif arg: - log.debug( str(arg) ) + log.debug(str(arg)) key = (service, controller) if key not in self.pusherrbacks: self.pusherrbacks[key] = list(args) @@ -367,21 +370,21 @@ def pusherrback(self, service, controller, *args): self.pushcheckbacks(key) def pushcheckbacks(self, key): - log.debug( "[PS] pushcheckbacks" ) + log.debug("[PS] pushcheckbacks") callparam = self.pushcallbacks.get(key, []) cntcall = len(callparam) errparam = self.pusherrbacks.get(key, []) cnterr = len(errparam) - cntservices = len( [ service for service in self.services if service.getEnable() ] ) - + cntservices = len([service for service in self.services if service.getEnable()]) + # Check if all services already called and returned - if ( cntservices == (cntcall + cnterr) ): + if (cntservices == (cntcall + cnterr)): service, controller = key if controller: # Check if no error is logged - if ( cnterr == 0 ): - log.debug( "[PS] controller.callback()" ) + if (cnterr == 0): + log.debug("[PS] controller.callback()") controller.callback() else: controller.errback() - log.debug( "[PS] controller.errback()" ) + log.debug("[PS] controller.errback()") diff --git a/src/ServiceBase.py b/src/ServiceBase.py index b440371..615b9a6 100644 --- a/src/ServiceBase.py +++ b/src/ServiceBase.py @@ -23,18 +23,17 @@ class ServiceBase(ModuleBase): # You only have to overwrite the functions You need # If You don't have to save something, You don't need getOptions / setOptions - + UniqueCounter = 0 - + ForceSingleInstance = True - + def __init__(self): ModuleBase.__init__(self) # Is called on instance creation ServiceBase.UniqueCounter += 1 self.uniqueid = ServiceBase.UniqueCounter - ################################################ # Base class functions @classmethod @@ -45,13 +44,13 @@ def forceSingle(cls): def resetUniqueID(): ServiceBase.UniqueCounter = 0 - ################################################ # Functions to be implemented in the plugin + def push(self, callback, errback, pluginname, subject, body="", attachments=[]): # Will be called, if a plugin wants to send a notification # At the end a service has to call one of the functions: callback or errback - errback( "Not implemented: " + self.getName() + ".push()") + errback("Not implemented: " + self.getName() + ".push()") # def test(self, plugin, subject, body="", attachments=[], callback=None, errback=None): # # Normally you don't have to overwrite this function diff --git a/src/Services/GNTP.py b/src/Services/GNTP.py index cd671ac..beb6a55 100644 --- a/src/Services/GNTP.py +++ b/src/Services/GNTP.py @@ -31,63 +31,64 @@ APP_NAME = _("{box:s} {name:s}") NOTIFICATION_TYPE = _("{name:s}") GROWL_SUBJECT_TEMPLATE = _("{box:s}: {subject:s}") -GROWL_BODY_TEMPLATE = _("{body:s}\n\n") \ +GROWL_BODY_TEMPLATE = _("{body:s}\n\n") \ + _("Donate {donate:s}") class GNTP(ServiceBase): - + ForceSingleInstance = False - + def __init__(self): # Is called on instance creation ServiceBase.__init__(self) #self.sockets = [] - + # Default configuration - self.setOption( 'growlhost', NoSave(ConfigText(default="host", fixed_size = False)), _("Growl Host name") ) - self.setOption( 'growlport', NoSave(ConfigNumber(default = 23053)), _("Growl Port") ) - self.setOption( 'timeout', NoSave(ConfigNumber(default = 3)), _("Timeout") ) - self.setOption( 'password', NoSave(ConfigPassword()), _("Password") ) - self.setOption( 'sticky', NoSave(ConfigYesNo(default = True)), _("Send as sticky") ) - self.setOption( 'priority', NoSave(ConfigNumber(default = 1)), _("Send with priority") ) + self.setOption('growlhost', NoSave(ConfigText(default="host", fixed_size=False)), _("Growl Host name")) + self.setOption('growlport', NoSave(ConfigNumber(default=23053)), _("Growl Port")) + self.setOption('timeout', NoSave(ConfigNumber(default=3)), _("Timeout")) + self.setOption('password', NoSave(ConfigPassword()), _("Password")) + self.setOption('sticky', NoSave(ConfigYesNo(default=True)), _("Send as sticky")) + self.setOption('priority', NoSave(ConfigNumber(default=1)), _("Send with priority")) def push(self, callback, errback, pluginname, subject, body="", attachments=[]): from Plugins.Extensions.PushService.plugin import NAME, VERSION, SUPPORT, DONATE - + box = config.pushservice.boxname.value - app = APP_NAME.format( **{'box': box, 'name': NAME} ) - nottype = NOTIFICATION_TYPE.format( **{'box': box, 'name': NAME} ) - + app = APP_NAME.format(**{'box': box, 'name': NAME}) + nottype = NOTIFICATION_TYPE.format(**{'box': box, 'name': NAME}) + # Prepare message - if body == "": body = subject - subject = GROWL_SUBJECT_TEMPLATE.format( **{'box': box, 'subject': subject} ) - body = GROWL_BODY_TEMPLATE.format( **{'body': str(body), 'name': NAME, 'version': VERSION, 'plugin': pluginname, 'support': SUPPORT, 'donate': DONATE} ) - + if body == "": + body = subject + subject = GROWL_SUBJECT_TEMPLATE.format(**{'box': box, 'subject': subject}) + body = GROWL_BODY_TEMPLATE.format(**{'body': str(body), 'name': NAME, 'version': VERSION, 'plugin': pluginname, 'support': SUPPORT, 'donate': DONATE}) + # Registrate growl = gntp.notifier.GrowlNotifier( - applicationName = app, - notifications = [nottype], - defaultNotifications = [nottype], - hostname = self.getValue('growlhost'), - port = self.getValue('growlport'), - password = self.getValue('password') + applicationName=app, + notifications=[nottype], + defaultNotifications=[nottype], + hostname=self.getValue('growlhost'), + port=self.getValue('growlport'), + password=self.getValue('password') ) growl.socketTimeout = self.getValue('timeout') growl.register() - + # Send a message - #socket = + #socket = sent = growl.notify( - noteType = nottype, - title = subject, - description = body, + noteType=nottype, + title=subject, + description=body, #Maybelater icon = "http://example.com/icon.png", - sticky = self.getValue('sticky'), - priority = self.getValue('priority') + sticky=self.getValue('sticky'), + priority=self.getValue('priority') ) #self.sockets.append(socket) - + if sent is True: callback() else: @@ -101,4 +102,4 @@ def push(self, callback, errback, pluginname, subject, body="", attachments=[]): # # Cancel push # if self.sockets: # for socket in self.sockets: -# socket.close() \ No newline at end of file +# socket.close() diff --git a/src/Services/PopUp.py b/src/Services/PopUp.py index 3d9dba8..65b2015 100644 --- a/src/Services/PopUp.py +++ b/src/Services/PopUp.py @@ -33,20 +33,20 @@ class PopUp(ServiceBase): - + ForceSingleInstance = True - + def __init__(self): # Is called on instance creation ServiceBase.__init__(self) # Default configuration - self.setOption( 'timeout', NoSave(ConfigNumber(default = 30)), _("Timeout") ) + self.setOption('timeout', NoSave(ConfigNumber(default=30)), _("Timeout")) def push(self, callback, errback, pluginname, subject, body="", attachments=[]): from Plugins.Extensions.PushService.plugin import NAME # Fire and forget AddPopup( - POPUP_TEMPLATE.format( **{'name': NAME, 'plugin': pluginname, 'subject': subject, 'body': body} ), + POPUP_TEMPLATE.format(**{'name': NAME, 'plugin': pluginname, 'subject': subject, 'body': body}), MessageBox.TYPE_INFO, self.getValue('timeout'), 'PS_PopUp_ID_' + subject diff --git a/src/Services/SMTP.py b/src/Services/SMTP.py index 7ea6525..fae6206 100644 --- a/src/Services/SMTP.py +++ b/src/Services/SMTP.py @@ -30,7 +30,7 @@ # Constants MAIL_HEADER_TEMPLATE = _("{box:s} {name:s}: {plugin:s}: {subject:s}") -MAIL_BODY_TEMPLATE = _("{body:s}\n\n") \ +MAIL_BODY_TEMPLATE = _("{body:s}\n\n") \ + _("Provided by Dreambox Plugin {name:s} {version:s} - {plugin:s}\n") \ + _("C 2012 by betonme @ IHAD\n") \ + _("Support {support:s}\n") \ @@ -38,61 +38,62 @@ class SMTP(ServiceBase): - + ForceSingleInstance = False - + def __init__(self): # Is called on instance creation ServiceBase.__init__(self) self.connectors = [] - + # Default configuration - self.setOption( 'smtpserver', NoSave(ConfigText(default="smtp.server.com", fixed_size = False)), _("SMTP Server") ) - self.setOption( 'smtpport', NoSave(ConfigNumber(default = 587)), _("SMTP Port") ) - self.setOption( 'smtpssl', NoSave(ConfigYesNo(default = True)), _("SMTP SSL") ) - self.setOption( 'smtptls', NoSave(ConfigYesNo(default = True)), _("SMTP TLS") ) - self.setOption( 'timeout', NoSave(ConfigNumber(default = 30)), _("Timeout") ) - - self.setOption( 'username', NoSave(ConfigText(default="user", fixed_size = False)), _("User name") ) - self.setOption( 'password', NoSave(ConfigPassword(default="password")), _("Password") ) - - self.setOption( 'mailfrom', NoSave(ConfigText(default = "abc@provider.com", fixed_size = False)), _("Mail from") ) - self.setOption( 'mailto', NoSave(ConfigText(fixed_size = False)), _("Mail to or leave empty (From will be used)") ) + self.setOption('smtpserver', NoSave(ConfigText(default="smtp.server.com", fixed_size=False)), _("SMTP Server")) + self.setOption('smtpport', NoSave(ConfigNumber(default=587)), _("SMTP Port")) + self.setOption('smtpssl', NoSave(ConfigYesNo(default=True)), _("SMTP SSL")) + self.setOption('smtptls', NoSave(ConfigYesNo(default=True)), _("SMTP TLS")) + self.setOption('timeout', NoSave(ConfigNumber(default=30)), _("Timeout")) + + self.setOption('username', NoSave(ConfigText(default="user", fixed_size=False)), _("User name")) + self.setOption('password', NoSave(ConfigPassword(default="password")), _("Password")) + + self.setOption('mailfrom', NoSave(ConfigText(default="abc@provider.com", fixed_size=False)), _("Mail from")) + self.setOption('mailto', NoSave(ConfigText(fixed_size=False)), _("Mail to or leave empty (From will be used)")) def push(self, callback, errback, pluginname, subject, body="", attachments=[]): from Plugins.Extensions.PushService.plugin import NAME, VERSION, SUPPORT, DONATE - + # Set SMTP parameters mailconf = {} - mailconf["host"] = self.getValue('smtpserver') - mailconf["port"] = self.getValue('smtpport') + mailconf["host"] = self.getValue('smtpserver') + mailconf["port"] = self.getValue('smtpport') mailconf["username"] = self.getValue('username') mailconf["password"] = self.getValue('password') - mailconf["ssl"] = self.getValue('smtpssl') - mailconf["tls"] = self.getValue('smtptls') - mailconf["timeout"] = self.getValue('timeout') - + mailconf["ssl"] = self.getValue('smtpssl') + mailconf["tls"] = self.getValue('smtptls') + mailconf["timeout"] = self.getValue('timeout') + # Create message object from_addr = self.getValue('mailfrom') to_addrs = [self.getValue('mailto') or from_addr] - + # Prepare message - if body == "": body = subject - subject = MAIL_HEADER_TEMPLATE.format( **{'box': config.pushservice.boxname.value, 'name': NAME, 'plugin': pluginname, 'subject': subject} ) - body = MAIL_BODY_TEMPLATE.format( **{'body': str(body), 'name': NAME, 'version': VERSION, 'plugin': pluginname, 'support': SUPPORT, 'donate': DONATE} ) + if body == "": + body = subject + subject = MAIL_HEADER_TEMPLATE.format(**{'box': config.pushservice.boxname.value, 'name': NAME, 'plugin': pluginname, 'subject': subject}) + body = MAIL_BODY_TEMPLATE.format(**{'body': str(body), 'name': NAME, 'version': VERSION, 'plugin': pluginname, 'support': SUPPORT, 'donate': DONATE}) message = Message(from_addr, to_addrs, subject, body) #TODO change mime="text/plain", charset="utf-8") if attachments: for attachment in attachments: message.attach(attachment) #TODO change mime=None, charset=None, content=None): - + # Send message - log.debug( ("PushService PushMail: Sending message: %s") % subject ) + log.debug(("PushService PushMail: Sending message: %s") % subject) deferred, connector = sendmail(mailconf, message) - + # Add callbacks deferred.addCallback(callback) deferred.addErrback(errback) - + self.connectors.append(connector) def cancel(self): diff --git a/src/Services/gntp/__init__.py b/src/Services/gntp/__init__.py index d8aef7e..ca0cc37 100644 --- a/src/Services/gntp/__init__.py +++ b/src/Services/gntp/__init__.py @@ -46,6 +46,7 @@ class UnsupportedError(BaseError): class _GNTPBuffer(StringIO.StringIO): """GNTP Buffer class""" + def writefmt(self, str="", *args): """Shortcut function for writing GNTP Headers""" self.write((str % args).encode('utf8', 'replace')) @@ -59,6 +60,7 @@ class _GNTPBase(object): :param string version: GNTP Protocol version :param string encription: Encryption protocol """ + def __init__(self, messagetype=None, version='1.0', encryption=None): self.info = { 'version': version, diff --git a/src/Services/gntp/cli.py b/src/Services/gntp/cli.py index a5801fa..a655169 100644 --- a/src/Services/gntp/cli.py +++ b/src/Services/gntp/cli.py @@ -8,6 +8,7 @@ # Plugin internal from Plugins.Extensions.PushService.Logger import log + class ClientParser(OptionParser): def __init__(self): OptionParser.__init__(self) @@ -45,7 +46,7 @@ def parse_args(self, args=None, values=None): values, args = OptionParser.parse_args(self, args, values) if values.message is None: - log.debug( 'Enter a message followed by Ctrl-D' ) + log.debug('Enter a message followed by Ctrl-D') try: message = sys.stdin.read() except KeyboardInterrupt: @@ -102,5 +103,6 @@ def main(): if result is not True: exit(result) + if __name__ == "__main__": main() diff --git a/src/Services/gntp/config.py b/src/Services/gntp/config.py index 3a7d3bc..beacee1 100644 --- a/src/Services/gntp/config.py +++ b/src/Services/gntp/config.py @@ -69,6 +69,7 @@ class GrowlNotifier(gntp.notifier.GrowlNotifier): password = ? port = ? """ + def __init__(self, applicationName='Python GNTP', notifications=[], defaultNotifications=None, applicationIcon=None, hostname='localhost', password=None, port=23053): @@ -100,6 +101,7 @@ def __init__(self, applicationName='Python GNTP', notifications=[], self.hostname = config.get('gntp', 'hostname') self.port = config.getint('gntp', 'port') + if __name__ == '__main__': # If we're running this module directly we're likely running it as a test # so extra debugging is useful diff --git a/src/Services/gntp/notifier.py b/src/Services/gntp/notifier.py index 92af597..9431b14 100644 --- a/src/Services/gntp/notifier.py +++ b/src/Services/gntp/notifier.py @@ -230,6 +230,7 @@ def _send(self, type, packet): logger.error('Invalid response: %s', response.error()) return response.error() + if __name__ == '__main__': # If we're running this module directly we're likely running it as a test # so extra debugging is useful diff --git a/src/Services/mail/mail.py b/src/Services/mail/mail.py index bc63dbc..d8229c7 100644 --- a/src/Services/mail/mail.py +++ b/src/Services/mail/mail.py @@ -41,60 +41,61 @@ from twisted.internet.ssl import ClientContextFactory from twisted.mail.smtp import ESMTPSenderFactory + class Message(object): def __init__(self, from_addr, to_addrs, subject, message, mime="text/plain", charset="utf-8"): self.subject = subject self.from_addr = from_addr self.to_addrs = isinstance(to_addrs, types.StringType) and [to_addrs] or to_addrs - + self.msg = None self.__cache = None self.message = MIMEText(message) self.message.set_charset(charset) self.message.set_type(mime) - + def attach(self, filename, mime=None, charset=None, content=None): base = os.path.basename(filename) if content is None: fd = open(filename) content = fd.read() fd.close() - + if not isinstance(content, types.StringType): raise TypeError("don't know how to handle content: %s" % type(content)) - + part = MIMEBase("application", "octet-stream") part.set_payload(content) Encoders.encode_base64(part) part.add_header("Content-Disposition", "attachment; filename=\"%s\"" % base) - + if mime is not None: part.set_type(mime) - + if charset is not None: part.set_charset(charset) - + if self.msg is None: self.msg = MIMEMultipart() self.msg.attach(self.message) - + self.msg.attach(part) - + def __str__(self): return self.__cache or "nuswit mail message: not rendered yet" - + def render(self): if self.msg is None: self.msg = self.message - + self.msg["Subject"] = self.subject self.msg["From"] = self.from_addr self.msg["To"] = COMMASPACE.join(self.to_addrs) self.msg["Date"] = formatdate(localtime=True) - + if self.__cache is None: self.__cache = self.msg.as_string() - + return StringIO(self.__cache) @@ -111,14 +112,14 @@ def sendmail(mailconf, message): """ if not isinstance(mailconf, types.DictType): raise TypeError("mailconf must be a regular python dictionary") - + if not isinstance(message, Message): raise TypeError("message must be an instance of nuswit.mail.Message") - + host = mailconf.get("host") if not isinstance(host, types.StringType): raise ValueError("mailconf requires a 'host' configuration") - + ssl = mailconf.get("ssl", True) tls = mailconf.get("tls", True) if ssl is True: @@ -128,13 +129,13 @@ def sendmail(mailconf, message): else: port = mailconf.get("port", 25) contextFactory = None - + retries = mailconf.get("retries", 0) timeout = mailconf.get("timeout", 30) - + if not isinstance(port, types.IntType): raise ValueError("mailconf requires a proper 'port' configuration") - + deferred = Deferred() username, password = mailconf.get("username"), mailconf.get("password") factory = ESMTPSenderFactory( @@ -144,10 +145,10 @@ def sendmail(mailconf, message): requireAuthentication=(username and password), requireTransportSecurity=tls, retries=retries, timeout=timeout) - + if not ssl: connector = reactor.connectTCP(host, port, factory, timeout=timeout) else: connector = reactor.connectSSL(host, port, factory, contextFactory, timeout=timeout) - + return deferred, connector diff --git a/src/__init__.py b/src/__init__.py index 08c4815..78da1ef 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -7,29 +7,29 @@ # Config options -config.pushservice = ConfigSubsection() +config.pushservice = ConfigSubsection() -config.pushservice.about = ConfigNothing() +config.pushservice.about = ConfigNothing() -config.pushservice.enable = ConfigEnableDisable(default = True) +config.pushservice.enable = ConfigEnableDisable(default=True) -config.pushservice.boxname = ConfigText(default = "Enigma2", fixed_size = False) -config.pushservice.xmlpath = ConfigText(default = "/etc/enigma2/pushservice.xml", fixed_size = False) +config.pushservice.boxname = ConfigText(default="Enigma2", fixed_size=False) +config.pushservice.xmlpath = ConfigText(default="/etc/enigma2/pushservice.xml", fixed_size=False) -config.pushservice.time = ConfigClock(default = 0) -config.pushservice.period = ConfigSelectionNumber(0, 1000, 1, default = 24) -config.pushservice.runonboot = ConfigEnableDisable(default = True) -config.pushservice.bootdelay = ConfigSelectionNumber(5, 1000, 5, default = 10) +config.pushservice.time = ConfigClock(default=0) +config.pushservice.period = ConfigSelectionNumber(0, 1000, 1, default=24) +config.pushservice.runonboot = ConfigEnableDisable(default=True) +config.pushservice.bootdelay = ConfigSelectionNumber(5, 1000, 5, default=10) -config.pushservice.push_errors = ConfigEnableDisable(default = False) +config.pushservice.push_errors = ConfigEnableDisable(default=False) -config.pushservice.popups_success_timeout = ConfigSelectionNumber(-1, 20, 1, default = 3) -config.pushservice.popups_warning_timeout = ConfigSelectionNumber(-1, 20, 1, default = -1) -config.pushservice.popups_error_timeout = ConfigSelectionNumber(-1, 20, 1, default = -1) +config.pushservice.popups_success_timeout = ConfigSelectionNumber(-1, 20, 1, default=3) +config.pushservice.popups_warning_timeout = ConfigSelectionNumber(-1, 20, 1, default=-1) +config.pushservice.popups_error_timeout = ConfigSelectionNumber(-1, 20, 1, default=-1) -config.pushservice.log_shell = ConfigEnableDisable(default = False) -config.pushservice.log_write = ConfigEnableDisable(default = False) -config.pushservice.log_file = ConfigText(default = "/tmp/pushservice.log", fixed_size = False) +config.pushservice.log_shell = ConfigEnableDisable(default=False) +config.pushservice.log_write = ConfigEnableDisable(default=False) +config.pushservice.log_file = ConfigText(default="/tmp/pushservice.log", fixed_size=False) def localeInit(): @@ -37,14 +37,16 @@ def localeInit(): os_environ["LANGUAGE"] = lang # Enigma doesn't set this (or LC_ALL, LC_MESSAGES, LANG). gettext needs it! gettext.bindtextdomain("PushService", resolveFilename(SCOPE_PLUGINS, "Extensions/PushService/locale")) + def _(txt): if txt: t = gettext.dgettext("PushService", txt) if t == txt: t = gettext.gettext(txt) - return t + return t else: return "" + localeInit() language.addCallback(localeInit) diff --git a/src/plugin.py b/src/plugin.py index 59d127a..2805e64 100644 --- a/src/plugin.py +++ b/src/plugin.py @@ -16,7 +16,9 @@ # ####################################################################### -import os, sys, traceback +import os +import sys +import traceback # Plugin from Plugins.Plugin import PluginDescriptor @@ -58,7 +60,7 @@ def setup(session, **kwargs): ### session.open(ConfigScreen.ConfigScreen) except Exception, e: - log.exception( ("PushService setup exception ") + str(e) ) + log.exception(("PushService setup exception ") + str(e)) ####################################################### @@ -71,20 +73,20 @@ def autostart(reason, **kwargs): gPushService = PushService() gPushService.start() except Exception, e: - log.exception( ("PushService autostart exception ") + str(e) ) + log.exception(("PushService autostart exception ") + str(e)) ####################################################### # Plugin main function def Plugins(**kwargs): - + descriptors = [] - + if config.pushservice.enable.value: # AutoStart - descriptors.append( PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart, needsRestart = False) ) - + descriptors.append(PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=autostart, needsRestart=False)) + #TODO icon - descriptors.append( PluginDescriptor(name = NAME, description = NAME + " " +_("configuration"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc = setup, needsRestart = False) ) #icon = "/icon.png" + descriptors.append(PluginDescriptor(name=NAME, description=NAME + " " + _("configuration"), where=PluginDescriptor.WHERE_PLUGINMENU, fnc=setup, needsRestart=False)) #icon = "/icon.png" return descriptors