def testBackup(): ua = UpdateAddon('Kenv99', 'script.service.kodi.callbacks', 'master', silent=True) assert isinstance(ua, UpdateAddon) ua.createTimeStampJson(translatepath('special://addon'), dst=None, ignore=['.git/*', '.idea/*', '*.pyc', '*.pyo']) result = ua.backup(translatepath('special://addon'), translatepath('special://addondata/backup')) os.remove(os.path.join(translatepath('special://addon'), 'timestamp.json')) assert result is True
def __init__(self, addonid=None, silent=False, numbackups=5): self.addonid = addonid self.addondir = translatepath('special://addon(%s)' % self.addonid) self.addondatadir = translatepath('special://addondata(%s)' % self.addonid) self.tmpdir = translatepath('%s/temp' % self.addondatadir) self.backupdir = translatepath('%s/backup' % self.addondatadir) self.silent = silent self.numbackups = numbackups
def start(self): oldsnapshots = WatchdogStartup.getPickle() newsnapshots = {} for setting in self.settings: folder = translatepath(setting['ws_folder']) if os.path.exists(folder): newsnapshot = DirectorySnapshot(folder, recursive=setting['ws_recursive']) newsnapshots[folder] = newsnapshot if folder in oldsnapshots.keys(): oldsnapshot = oldsnapshots[folder] diff = DirectorySnapshotDiff(oldsnapshot, newsnapshot) changes = self.getChangesFromDiff(diff) if len(changes) > 0: eh = EventHandler(patterns=setting['ws_patterns'].split(','), ignore_patterns=setting['ws_ignore_patterns'].split(','), ignore_directories=setting['ws_ignore_directories']) observer = Observer() try: observer.schedule(eh, folder, recursive=setting['ws_recursive']) time.sleep(0.25) for change in changes: eh.dispatch(change) time.sleep(0.25) try: observer.unschedule_all() except Exception: pass except Exception: raise if len(eh.data) > 0: message = Message(Topic('onStartupFileChanges', setting['key']), listOfChanges=eh.data) self.publish(message) else: message = Message(Topic('onStartupFileChanges', setting['key']), listOfChanges=[{'DirsDeleted':folder}]) log(msg=_('Watchdog Startup folder not found: %s') % folder) self.publish(message)
def cls_init(cls): cls.pofn = translatepath( 'special://addon/resources/language/English/strings.po') cls.isStub = xbmcaddon.Addon().getAddonInfo('id') == '' cls.podict = PoDict() cls.podict.read_from_file(cls.pofn) cls.updateAlways = False
def process_cmdline(cmd): posspaths = [] cmds = cmd.encode('utf-8') partss = shlex.split(cmds, posix=not sys.platform.lower().startswith('win')) parts = [] for part in partss: parts.append(unicode(part, encoding='utf-8')) for i in xrange(0, len(parts)): found = -1 for j in xrange(i + 1, len(parts) + 1): t = u' '.join(parts[i:j]) t = translatepath(t) t = t.strip(u'"') if os.path.exists(t): if j > found: found = j if found != -1: posspaths.append([i, found]) paths = [] args = [] if len(posspaths) > 0: for i, path in enumerate(posspaths): # Check for overlaps if i > 0: if path[0] < posspaths[i - 1][1]: pass # If possible paths overlap, treat the first as a path and treat the rest of the overlap as non-path else: paths.append(path) else: paths.append(path) for i in xrange(0, len(parts)): for j in xrange(0, len(paths)): if i == paths[j][0]: t = u' '.join(parts[i:paths[j][1]]) t = translatepath(t) t = t.strip(u'"') parts[i] = t for k in xrange(i + 1, paths[j][1]): parts[k] = u'' for i in xrange(0, len(parts)): if parts[i] != u'': args.append(parts[i]) else: args = parts return args
def process_cmdline(cmd): posspaths = [] cmds = cmd.encode('utf-8') partss = shlex.split(cmds, posix= not sys.platform.lower().startswith('win')) parts = [] for part in partss: parts.append(unicode(part, encoding='utf-8')) for i in xrange(0, len(parts)): found=-1 for j in xrange(i+1, len(parts)+1): t = u' '.join(parts[i:j]) t = translatepath(t) t = t.strip(u'"') if os.path.exists(t): if j > found: found = j if found != -1: posspaths.append([i, found]) paths = [] args = [] if len(posspaths) > 0: for i, path in enumerate(posspaths): # Check for overlaps if i > 0: if path[0] < posspaths[i-1][1]: pass # If possible paths overlap, treat the first as a path and treat the rest of the overlap as non-path else: paths.append(path) else: paths.append(path) for i in xrange(0, len(parts)): for j in xrange(0, len(paths)): if i == paths[j][0]: t = u' '.join(parts[i:paths[j][1]]) t = translatepath(t) t = t.strip(u'"') parts[i] = t for k in xrange(i+1, paths[j][1]): parts[k]=u'' for i in xrange(0, len(parts)): if parts[i] != u'': args.append(parts[i]) else: args = parts return args
def run(self): if self.taskKwargs['notify'] is True: notify( _('Task %s launching for event: %s') % (self.taskId, str(self.topic))) err = False msg = '' args = self.runtimeargs try: useImport = self.taskKwargs['import'] except KeyError: useImport = False fn = translatepath(self.taskKwargs['pythonfile']) try: if len(self.runtimeargs) > 0: if useImport is False: args = ' %s' % ' '.join(args) result = xbmc.executebuiltin('XBMC.RunScript(%s, %s)' % (fn, args)) else: directory, module_name = os.path.split(fn) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name) result = module.run(args) finally: sys.path[:] = path else: if useImport is False: result = xbmc.executebuiltin('XBMC.RunScript(%s)' % fn) else: directory, module_name = os.path.split(fn) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name) result = module.run(args) finally: sys.path[:] = path if result is not None: msg = result if result != '': err = True except Exception: e = sys.exc_info()[0] err = True if hasattr(e, 'message'): msg = str(e.message) msg = msg + '\n' + traceback.format_exc() self.threadReturn(err, msg)
def abort(self, *args): snapshots = {} for setting in self.settings: folder = xbmc.translatePath(setting['ws_folder']) if folder == u'': folder = setting['ws_folder'] folder = translatepath(folder) if os.path.exists(folder): snapshot = DirectorySnapshot(folder, recursive=setting['ws_recursive']) snapshots[folder] = snapshot WatchdogStartup.savePickle(snapshots)
def initialize(self): for setting in self.watchdogSettings: patterns = setting['patterns'].split(',') ignore_patterns = setting['ignore_patterns'].split(',') eh = EventHandler(patterns=patterns, ignore_patterns=ignore_patterns, ignore_directories=setting['ignore_directories'], topic=Topic('onFileSystemChange', setting['key']), publish=self.publish) self.event_handlers.append(eh) folder = translatepath(setting['folder']) mysetting = [eh, folder, setting['recursive']] self.observersettings.append(mysetting)
def run(self): if self.taskKwargs['notify'] is True: notify(_('Task %s launching for event: %s') % (self.taskId, str(self.topic))) err = False msg = '' args = self.runtimeargs try: useImport = self.taskKwargs['import'] except KeyError: useImport = False fn = translatepath(self.taskKwargs['pythonfile']) try: if len(self.runtimeargs) > 0: if useImport is False: args = ' %s' % ' '.join(args) result = xbmc.executebuiltin('XBMC.RunScript(%s, %s)' % (fn, args)) else: directory, module_name = os.path.split(fn) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name) result = module.run(args) finally: sys.path[:] = path else: if useImport is False: result = xbmc.executebuiltin('XBMC.RunScript(%s)' % fn) else: directory, module_name = os.path.split(fn) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name) result = module.run(args) finally: sys.path[:] = path if result is not None: msg = result if result != '': err = True except Exception: e = sys.exc_info()[0] err = True if hasattr(e, 'message'): msg = str(e.message) msg = msg + '\n' + traceback.format_exc() self.threadReturn(err, msg)
def __init__(self, username, reponame, branch='master', src_root=None, addonid=None, silent=False, numbackups=5): self.username = username self.reponame = reponame self.branch = branch self.zipurl = r'https://github.com/%s/%s/archive/%s.zip' % (username, reponame, branch) if src_root is None: self.addonxmlurl = r'https://raw.githubusercontent.com/%s/%s/%s/addon.xml' % (username, reponame, branch) else: self.addonxmlurl = r'https://raw.githubusercontent.com/%s/%s/%s/%s/addon.xml' % (username, reponame, branch, src_root) if addonid is None: self.addonid = reponame else: self.addonid = addonid self.addondir = translatepath('special://addon(%s)' % self.addonid) self.addondatadir = translatepath('special://addondata(%s)' % self.addonid) self.tmpdir = translatepath('%s/temp' % self.addondatadir) self.backupdir = translatepath('%s/backup' % self.addondatadir) self.currentversion = xbmcaddon.Addon(self.addonid).getAddonInfo('version') if self.currentversion == u'': # Running stub self.currentversion = '0.9.0' self.silent = silent self.numbackups = numbackups
def start(self): oldsnapshots = WatchdogStartup.getPickle() newsnapshots = {} for setting in self.settings: folder = translatepath(setting['ws_folder']) if os.path.exists(folder): newsnapshot = DirectorySnapshot( folder, recursive=setting['ws_recursive']) newsnapshots[folder] = newsnapshot if oldsnapshots is not None: if folder in oldsnapshots.keys(): oldsnapshot = oldsnapshots[folder] diff = DirectorySnapshotDiff(oldsnapshot, newsnapshot) changes = self.getChangesFromDiff(diff) if len(changes) > 0: eh = EventHandler( patterns=setting['ws_patterns'].split(','), ignore_patterns=setting['ws_ignore_patterns']. split(','), ignore_directories=setting[ 'ws_ignore_directories']) observer = Observer() try: observer.schedule( eh, folder, recursive=setting['ws_recursive']) time.sleep(0.5) for change in changes: eh.dispatch(change) time.sleep(0.25) try: observer.unschedule_all() except Exception: pass except Exception: raise if len(eh.data) > 0: message = Message(Topic( 'onStartupFileChanges', setting['key']), listOfChanges=eh.data) self.publish(message) else: message = Message(Topic('onStartupFileChanges', setting['key']), listOfChanges=[{ 'DirsDeleted': folder }]) log(msg=_('Watchdog Startup folder not found: %s') % folder) self.publish(message)
def setup(self): self.folder = translatepath('special://addon/resources/lib/tests') setPathRW(self.folder) watchdogSettings = [{'folder':self.folder, 'patterns':'*', 'ignore_patterns':'', 'ignore_directories':True, 'recursive':False, 'key':'E1'}] self.dispatcher = Dispatcher() self.subscriber = testSubscriber() self.topic = Topic('onFileSystemChange','E1') self.subscriber.addTopic(self.topic) self.dispatcher.addSubscriber(self.subscriber) settings = Settings() flexmock(settings, getWatchdogSettings=watchdogSettings) self.publisher = WatchdogPublisher(self.dispatcher, settings) self.dispatcher.start()
def setup(self): self.folder = translatepath('special://addon/resources/lib/tests') watchdogStartupSettings = [{'ws_folder':self.folder, 'ws_patterns':'*', 'ws_ignore_patterns':'', 'ws_ignore_directories':True, 'ws_recursive':False, 'key':'E1'}] self.saveduserpickle = WatchdogStartup.getPickle() self.dispatcher = Dispatcher() self.subscriber = testSubscriber() self.topic = Topic('onStartupFileChanges','E1') self.subscriber.addTopic(self.topic) self.dispatcher.addSubscriber(self.subscriber) settings = Settings() flexmock(settings, getWatchdogStartupSettings=watchdogStartupSettings) self.publisher = WatchdogStartup(self.dispatcher, settings) self.dispatcher.start()
def validate(taskKwargs, xlog=KodiLogger.log): tmp = translatepath(taskKwargs['pythonfile']) fse = sys.getfilesystemencoding() if fse is None: fse = 'utf-8' if sys.platform.lower().startswith('win'): if tmp.encode('utf-8') != tmp.encode(fse): tmp = fsencode(tmp) if xbmcvfs.exists(tmp): ext = os.path.splitext(tmp)[1] if ext.lower() == '.py': return True else: xlog(msg=_('Error - not a python script: %s') % tmp) return False else: xlog(msg=_('Error - File not found: %s') % tmp) return False
def setup(self): self.folder = translatepath('special://addon/resources/lib/tests') watchdogStartupSettings = [{ 'ws_folder': self.folder, 'ws_patterns': '*', 'ws_ignore_patterns': '', 'ws_ignore_directories': True, 'ws_recursive': False, 'key': 'E1' }] self.saveduserpickle = WatchdogStartup.getPickle() self.dispatcher = Dispatcher() self.subscriber = testSubscriber() self.topic = Topic('onStartupFileChanges', 'E1') self.subscriber.addTopic(self.topic) self.dispatcher.addSubscriber(self.subscriber) settings = Settings() flexmock(settings, getWatchdogStartupSettings=watchdogStartupSettings) self.publisher = WatchdogStartup(self.dispatcher, settings) self.dispatcher.start()
def setup(self): self.folder = translatepath('special://addon/resources/lib/tests') setPathRW(self.folder) watchdogSettings = [{ 'folder': self.folder, 'patterns': '*', 'ignore_patterns': '', 'ignore_directories': True, 'recursive': False, 'key': 'E1' }] self.dispatcher = Dispatcher() self.subscriber = testSubscriber() self.topic = Topic('onFileSystemChange', 'E1') self.subscriber.addTopic(self.topic) self.dispatcher.addSubscriber(self.subscriber) settings = Settings() flexmock(settings, getWatchdogSettings=watchdogSettings) self.publisher = WatchdogPublisher(self.dispatcher, settings) self.dispatcher.start()
def setup(self): self.folder = translatepath("special://addon/resources/lib/tests") setPathRW(self.folder) watchdogSettings = [ { "folder": self.folder, "patterns": "*", "ignore_patterns": "", "ignore_directories": True, "recursive": False, "key": "E1", } ] self.dispatcher = Dispatcher() self.subscriber = MockSubscriber() self.topic = Topic("onFileSystemChange", "E1") self.subscriber.addTopic(self.topic) self.dispatcher.addSubscriber(self.subscriber) settings = Settings() flexmock(settings, getWatchdogSettings=watchdogSettings) self.publisher = WatchdogPublisher(self.dispatcher, settings) self.dispatcher.start()
def setup(self): self.folder = translatepath("special://addon/resources/lib/tests") watchdogStartupSettings = [ { "ws_folder": self.folder, "ws_patterns": "*", "ws_ignore_patterns": "", "ws_ignore_directories": True, "ws_recursive": False, "key": "E1", } ] self.saveduserpickle = WatchdogStartup.getPickle() self.dispatcher = Dispatcher() self.subscriber = MockSubscriber() self.topic = Topic("onStartupFileChanges", "E1") self.subscriber.addTopic(self.topic) self.dispatcher.addSubscriber(self.subscriber) settings = Settings() flexmock(settings, getWatchdogStartupSettings=watchdogStartupSettings) self.publisher = WatchdogStartup(self.dispatcher, settings) self.dispatcher.start()
def createUserTasks(): paths = [translatepath('special://addondata')] try: setPathRW(paths[0]) except OSError: pass paths.append(os.path.join(paths[0], 'lib')) paths.append(os.path.join(paths[1], 'usertasks')) for path in paths: if not os.path.isdir(path): try: os.mkdir(path) setPathExecuteRW(path) except OSError: pass for path in paths[1:]: fn = os.path.join(path, '__init__.py') if not os.path.isfile(fn): try: with open(fn, mode='w') as f: f.writelines('') setPathExecuteRW(fn) except (OSError, IOError): pass
def run(self): if self.taskKwargs['notify'] is True: notify( _('Task %s launching for event: %s') % (self.taskId, str(self.topic))) err = False msg = '' args = self.runtimeargs try: useImport = self.taskKwargs['import'] except KeyError: useImport = False fn = translatepath(self.taskKwargs['pythonfile']) fse = sys.getfilesystemencoding() if fse is None: fse = 'utf-8' if sys.platform.lower().startswith('win'): if fn.encode('utf-8') != fn.encode(fse): fn = fsencode(fn) else: fn = fn.encode(fse) try: if len(self.runtimeargs) > 0: if useImport is False: args = u' %s' % ' '.join(args) try: args = args.encode(fse) except UnicodeEncodeError: msg += 'Unicode Encode Error for "%s" Encoder: %s' % ( args, fse) result = xbmc.executebuiltin('XBMC.RunScript(%s, %s)' % (fn, args)) else: directory, module_name = os.path.split( self.taskKwargs['pythonfile']) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name.encode('utf-8')) result = module.run(args) finally: sys.path[:] = path else: if useImport is False: result = xbmc.executebuiltin(u'XBMC.RunScript(%s)' % fn) else: directory, module_name = os.path.split(fn) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name.encode('utf-8')) result = module.run(None) finally: sys.path[:] = path if result is not None: msg = result if result != '': err = True except Exception: e = sys.exc_info()[0] err = True msg = u'' if hasattr(e, 'message'): msg += unicode(e.message) + u'\n' msg += unicode(e) + u'\n' tb = traceback.format_exc() msg += tb.decode('utf-8') self.threadReturn(err, msg)
def installFromZip(self, zipfn, dryrun=False, updateonly=None, deletezip=False): if os.path.split(os.path.split(zipfn)[0])[1] == 'backup': log(msg='Installing from backup') isBackup = True else: isBackup = False unzipdir = os.path.join(self.addondatadir, 'tmpunzip') if self.unzip(zipfn, unzipdir) is False: self.notify(_('Downloaded file could not be extracted')) try: os.remove(zipfn) except OSError: pass try: shutil.rmtree(unzipdir) except OSError: pass return else: if deletezip: os.remove(zipfn) if not isBackup: if self.backup(self.addondir, self.backupdir, self.numbackups) is False: self.notify(_('Backup failed, update aborted')) return else: log(msg='Backup succeeded.') archivedir = os.path.join(unzipdir, '%s-%s' %(self.reponame, self.branch)) addonisGHA = self.isGitHubArchive(self.addondir) if os.path.isfile(os.path.join(archivedir, 'timestamp.json')) and not isBackup: fd = self.loadfiledates(os.path.join(archivedir, 'timestamp.json')) path = os.path.join(unzipdir, '%s-%s' %(self.addonid, self.branch)) self.setfiledates(path, fd) log(msg='File timestamps updated') if updateonly is None: updateonly = True else: if updateonly is None: updateonly = False if updateonly is True and addonisGHA: updateonly = False install_root = self.getAddonxmlPath(archivedir) if install_root != '': try: fc = self.copyToDir(install_root, self.addondir, updateonly=updateonly, dryrun=dryrun) except OSError as e: self.notify(_('Error encountered copying to addon directory: %s') % str(e)) shutil.rmtree(unzipdir) self.cleartemp(recreate=False) else: if len(fc) > 0: self.cleartemp(recreate=False) shutil.rmtree(unzipdir) if self.silent is False: msg = _('New version installed') if not isBackup: msg += _('\nPrevious installation backed up') self.notify(msg) log(msg='The following files were updated: %s' % str(fc)) if self.prompt(_('Attempt to restart addon now?')): restartpath = translatepath('special://addon{%s)/restartaddon.py' % self.addonid) if not os.path.isfile(restartpath): self.createRestartPy(restartpath) xbmc.executebuiltin('RunScript(%s, %s)' % (restartpath, self.addonid)) else: self.notify(_('All files are current')) self.cleartemp(recreate=False) shutil.rmtree(unzipdir) else: self.notify(_('Could not find addon.xml\nInstallation aborted'))
import traceback import json from resources.lib import taskdict from resources.lib.pubsub import Topic, TaskManager from resources.lib.events import Events from resources.lib.kodilogging import KodiLogger from resources.lib.utils.kodipathtools import translatepath, setPathExecuteRW import xbmc from resources.lib.utils.poutil import KodiPo kodipo = KodiPo() _ = kodipo.getLocalizedString kl = KodiLogger() log = kl.log events = Events().AllEvents isAndroid = 'XBMC_ANDROID_SYSTEM_LIBS' in os.environ.keys() testdir = translatepath('special://addon/resources/lib/tests') setPathExecuteRW(testdir) def is_xbmc_debug(): json_query = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method": "Settings.GetSettingValue", "params": {"setting":"debug.showloginfo"} }') json_query = str(json_query) json_response = json.loads(json_query) if json_response.has_key('result'): if json_response['result'].has_key('value'): return json_response['result']['value'] else: raise SyntaxError('Bad JSON') else: raise SyntaxError('Bad JSON')
def getPicklePath(): path = translatepath('special://addondata/watchdog.pkl') setPathRW(os.path.split(path)[0]) return path
def installFromZip(self, zipfn, dryrun=False, updateonly=None, deletezip=False, silent=False): if os.path.split(os.path.split(zipfn)[0])[1] == 'backup': log(msg='Installing from backup') isBackup = True else: isBackup = False unzipdir = os.path.join(self.addondatadir, 'tmpunzip') if UpdateAddon.unzip(zipfn, unzipdir) is False: UpdateAddon.notify(_('Downloaded file could not be extracted')) try: os.remove(zipfn) except OSError: pass try: shutil.rmtree(unzipdir) except OSError: pass return else: if deletezip: os.remove(zipfn) branch = UpdateAddon.getBranchFromFile(unzipdir) installedbranch = xbmcaddon.Addon().getSetting('installedbranch') if branch == '': branch = installedbranch if not isBackup: if self.backup(self.addondir, self.backupdir, self.numbackups) is False: UpdateAddon.notify(_('Backup failed, update aborted'), silent=silent) return else: log(msg='Backup succeeded.') archivedir = UpdateAddon.getAddonxmlPath(unzipdir) addonisGHA = UpdateAddon.isGitHubArchive(self.addondir) if os.path.isfile(os.path.join(archivedir, 'timestamp.json')) and not isBackup: fd = UpdateAddon.loadfiledates(os.path.join(archivedir, 'timestamp.json')) UpdateAddon.setfiledates(archivedir, fd) log(msg='File timestamps updated') if updateonly is None: updateonly = True ziptimestamped = True else: ziptimestamped = False if updateonly is None: updateonly = False if updateonly is True and addonisGHA: updateonly = False if updateonly is True and ziptimestamped is False and isBackup is False: updateonly = False if installedbranch != branch: updateonly = False if archivedir != '': try: fc = copyToDir(archivedir, self.addondir, updateonly=updateonly, dryrun=dryrun) except OSError as e: UpdateAddon.notify(_('Error encountered copying to addon directory: %s') % str(e), silent=silent) shutil.rmtree(unzipdir) self.cleartemp(recreate=False) else: if installedbranch != branch: xbmcaddon.Addon().setSetting('installedbranch', branch) if len(fc) > 0: self.cleartemp(recreate=False) shutil.rmtree(unzipdir) if silent is False: if not isBackup: msg = _('New version installed') msg += _('\nPrevious installation backed up') else: msg = _('Backup restored') UpdateAddon.notify(msg) log(msg=_('The following files were updated: %s') % str(fc)) if not silent: answer = UpdateAddon.prompt(_('Attempt to restart addon now?')) == True else: answer = True if answer is True: restartpath = translatepath('special://addon{%s)/restartaddon.py' % self.addonid) if not os.path.isfile(restartpath): self.createRestartPy(restartpath) xbmc.executebuiltin('RunScript(%s, %s)' % (restartpath, self.addonid)) else: UpdateAddon.notify(_('All files are current'), silent=silent) else: self.cleartemp(recreate=False) shutil.rmtree(unzipdir) UpdateAddon.notify(_('Could not find addon.xml\nInstallation aborted'), silent=silent)
elif sys.argv[1] == 'test': KodiLogger.setLogLevel(KodiLogger.LOGNOTICE) from resources.lib.tests.testTasks import testTasks tt = testTasks() tt.runTests() dialog = xbmcgui.Dialog() msg = _('Native Task Testing Complete - see log for results') dialog.notification(_('Kodi Callbacks'), msg, xbmcgui.NOTIFICATION_INFO, 5000) elif sys.argv[1] == 'updatefromzip': from resources.lib.utils.updateaddon import UpdateAddon KodiLogger.setLogLevel(KodiLogger.LOGNOTICE) dialog = xbmcgui.Dialog() zipfn = dialog.browse(1, _('Locate zip file'), 'files', '.zip', False, False, translatepath('~')) if zipfn != translatepath('~'): if os.path.isfile(zipfn): ua = UpdateAddon(addonid) ua.installFromZip(zipfn, updateonly=True, dryrun=dryrun) else: dialog.ok(_('Kodi Callbacks'), _('Incorrect path')) elif sys.argv[1] == 'restorebackup': KodiLogger.setLogLevel(KodiLogger.LOGNOTICE) dialog = xbmcgui.Dialog() zipfn = dialog.browse(1, _('Locate backup zip file'), 'files', '.zip', False, False, translatepath('special://addondata/backup/')) if zipfn != translatepath('special://addondata/backup/'): from resources.lib.utils.updateaddon import UpdateAddon
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys from resources.lib.pubsub import Publisher, Message, Topic from resources.lib.events import Events from resources.lib.utils.kodipathtools import translatepath try: from watchdog.observers import Observer from watchdog.events import PatternMatchingEventHandler except ImportError: libs = translatepath('special://addon/resources/lib') sys.path.append(libs) libs = translatepath('special://addon/resources/lib/watchdog') sys.path.append(libs) try: from resources.lib.watchdog.observers import Observer from resources.lib.watchdog.events import PatternMatchingEventHandler except ImportError: raise class EventHandler(PatternMatchingEventHandler): def __init__(self, patterns, ignore_patterns, ignore_directories, topic, publish): super(EventHandler, self).__init__(patterns=patterns,
def run(self): if self.taskKwargs['notify'] is True: notify(_('Task %s launching for event: %s') % (self.taskId, str(self.topic))) err = False msg = '' args = self.runtimeargs try: useImport = self.taskKwargs['import'] except KeyError: useImport = False fn = translatepath(self.taskKwargs['pythonfile']) fse = sys.getfilesystemencoding() if fse is None: fse = 'utf-8' if sys.platform.lower().startswith('win'): if fn.encode('utf-8') != fn.encode(fse): fn = fsencode(fn) else: fn = fn.encode(fse) try: if len(self.runtimeargs) > 0: if useImport is False: args = u' %s' % ' '.join(args) try: args = args.encode(fse) except UnicodeEncodeError: msg += 'Unicode Encode Error for "%s" Encoder: %s' % (args, fse) result = xbmc.executebuiltin('XBMC.RunScript(%s, %s)' % (fn, args)) else: directory, module_name = os.path.split(self.taskKwargs['pythonfile']) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name.encode('utf-8')) result = module.run(args) finally: sys.path[:] = path else: if useImport is False: result = xbmc.executebuiltin(u'XBMC.RunScript(%s)' % fn) else: directory, module_name = os.path.split(fn) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name.encode('utf-8')) result = module.run(None) finally: sys.path[:] = path if result is not None: msg = result if result != '': err = True except Exception: e = sys.exc_info()[0] err = True msg = u'' if hasattr(e, 'message'): msg += unicode(e.message) + u'\n' msg += unicode(e) + u'\n' tb = traceback.format_exc() msg += tb.decode('utf-8') self.threadReturn(err, msg)
class testLog(object): path = translatepath('special://addondata') if not os.path.exists(path): os.mkdir(path) setPathRW(path) fn = translatepath('special://addondata/kodi.log') def __init__(self): self.publisher = None self.dispatcher = None self.subscriber = None self.globalidletime = None self.starttime = None self.topics = None @staticmethod def logSimulate(): import random, string randomstring = ''.join( random.choice(string.lowercase) for i in range(30)) + '\n' targetstring = '%s%s%s' % (randomstring[:12], 'kodi_callbacks', randomstring[20:]) for i in xrange(0, 10): with open(testLog.fn, 'a') as f: if i == 5: f.writelines(targetstring) else: f.writelines(randomstring) time.sleep(0.25) def setup(self): flexmock(log, logfn=testLog.fn) flexmock(log.xbmc, log=printlog) flexmock(log.xbmc, sleep=sleep) self.dispatcher = Dispatcher() self.subscriber = testSubscriber() def teardown(self): self.publisher.abort() self.dispatcher.abort() del self.publisher del self.dispatcher def testLogSimple(self): self.topics = [Topic('onLogSimple', 'E1')] xsettings = [{ 'matchIf': 'kodi_callbacks', 'rejectIf': '', 'eventId': 'E1' }] settings = Settings() flexmock(settings, getLogSimples=xsettings) flexmock(settings, general={'LogFreq': 100}) self.publisher = LogPublisher(self.dispatcher, settings) try: os.remove(testLog.fn) except OSError: pass finally: with open(testLog.fn, 'w') as f: f.writelines('') self.subscriber.addTopic(self.topics[0]) self.dispatcher.addSubscriber(self.subscriber) self.dispatcher.start() self.publisher.start() t = threading.Thread(target=testLog.logSimulate) t.start() t.join() self.publisher.abort() self.dispatcher.abort() time.sleep(2) try: os.remove(testLog.fn) except OSError: pass messages = self.subscriber.retrieveMessages() msgtopics = [msg.topic for msg in messages] for topic in self.topics: assert topic in msgtopics def testLogRegex(self): self.topics = [Topic('onLogRegex', 'E1')] xsettings = [{ 'matchIf': 'kodi_callbacks', 'rejectIf': '', 'eventId': 'E1' }] settings = Settings() flexmock(settings, getLogRegexes=xsettings) flexmock(settings, general={'LogFreq': 100}) self.publisher = LogPublisher(self.dispatcher, settings) try: os.remove(testLog.fn) except OSError: pass finally: with open(testLog.fn, 'w') as f: f.writelines('') self.subscriber.addTopic(self.topics[0]) self.dispatcher.addSubscriber(self.subscriber) self.dispatcher.start() self.publisher.start() t = threading.Thread(target=testLog.logSimulate) t.start() t.join() self.publisher.abort() self.dispatcher.abort() time.sleep(2) try: os.remove(testLog.fn) except OSError: pass messages = self.subscriber.retrieveMessages() msgtopics = [msg.topic for msg in messages] for topic in self.topics: assert topic in msgtopics
def cls_init(cls): cls.pofn = translatepath('special://addon/resources/language/English/strings.po') cls.isStub = xbmcaddon.Addon().getAddonInfo('id') == '' cls.podict = PoDict() cls.podict.read_from_file(cls.pofn) cls.updateAlways = False
generate_settingsxml() elif sys.argv[1] == 'test': KodiLogger.setLogLevel(KodiLogger.LOGNOTICE) from resources.lib.tests.testTasks import testTasks tt = testTasks() tt.runTests() dialog = xbmcgui.Dialog() msg = _('Native Task Testing Complete - see log for results') dialog.notification('Kodi Callbacks', msg, xbmcgui.NOTIFICATION_INFO, 5000) elif sys.argv[1] == 'updatefromzip': from resources.lib.utils.kodipathtools import translatepath KodiLogger.setLogLevel(KodiLogger.LOGNOTICE) dialog = xbmcgui.Dialog() zipfn = dialog.browse(1, _('Locate zip file'), 'files', '.zip', False, False, translatepath('~')) if zipfn != translatepath('~'): if os.path.isfile(zipfn): from resources.lib.utils.updateaddon import UpdateAddon ua = UpdateAddon('KenV99', 'script.service.kodi.callbacks', 'master', addonid='script.service.kodi.callbacks') ua.installFromZip(zipfn, updateonly=True, dryrun=False) elif sys.argv[1] == 'restorebackup': from resources.lib.utils.kodipathtools import translatepath KodiLogger.setLogLevel(KodiLogger.LOGNOTICE) dialog = xbmcgui.Dialog() zipfn = dialog.browse(1, _('Locate backup zip file'), 'files', '.zip', False, False, translatepath('special://addondata/backup/'))
# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys import pickle import os import time from resources.lib.utils.kodipathtools import translatepath, setPathRW libs = translatepath('special://addon/resources/lib') sys.path.append(libs) libs = translatepath('special://addon/resources/lib/watchdog') sys.path.append(libs) import xbmc from resources.lib.events import Events from resources.lib.watchdog.utils.dirsnapshot import DirectorySnapshot, DirectorySnapshotDiff from resources.lib.watchdog.observers import Observer from resources.lib.watchdog.events import PatternMatchingEventHandler, FileSystemEvent, EVENT_TYPE_CREATED, EVENT_TYPE_DELETED, EVENT_TYPE_MODIFIED, EVENT_TYPE_MOVED from resources.lib.pubsub import Publisher, Message, Topic from resources.lib.utils.poutil import KodiPo kodipo = KodiPo() _ = kodipo.getLocalizedString from resources.lib.kodilogging import KodiLogger klogger = KodiLogger()
# You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import xbmcaddon from resources.lib import taskdict from resources.lib.events import Events from resources.lib.events import requires_subtopic from resources.lib.kodilogging import KodiLogger from resources.lib.pubsub import Topic from resources.lib.utils.kodipathtools import translatepath from resources.lib.utils.poutil import PoDict podict = PoDict() podict.read_from_file( translatepath('special://addon/resources/language/English/strings.po')) def getEnglishStringFromId(msgctxt): status, ret = podict.has_msgctxt(msgctxt) if status is True: return ret else: return '' _ = getEnglishStringFromId try: addonid = xbmcaddon.Addon('script.service.kodi.callbacks').getAddonInfo( 'id')
os.mkdir(path) setPathExecuteRW(path) except OSError: pass for path in paths[1:]: fn = os.path.join(path, '__init__.py') if not os.path.isfile(fn): try: with open(fn, mode='w') as f: f.writelines('') setPathExecuteRW(fn) except (OSError, IOError): pass dirn = translatepath(r'special://addondata/lib') usertasks = None createUserTasks() sys.path.insert(0, dirn) try: import usertasks except ImportError: usertasks = None log(msg='Failed importing usertasks from addondata') if usertasks is None: packages = [tasks] else: packages = [tasks, usertasks] taskdict = {} tasktypes = [] for package in packages:
import traceback import json from resources.lib import taskdict from resources.lib.pubsub import Topic, TaskManager from resources.lib.events import Events from resources.lib.kodilogging import KodiLogger from resources.lib.utils.kodipathtools import translatepath, setPathExecuteRW import xbmc from resources.lib.utils.poutil import KodiPo kodipo = KodiPo() _ = kodipo.getLocalizedString kl = KodiLogger() log = kl.log events = Events().AllEvents isAndroid = 'XBMC_ANDROID_SYSTEM_LIBS' in os.environ.keys() testdir = translatepath('special://addon/resources/lib/tests') setPathExecuteRW(testdir) def is_xbmc_debug(): json_query = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "id": 0, "method": "Settings.GetSettingValue", "params": {"setting":"debug.showloginfo"} }') json_query = unicode(json_query, 'utf-8', errors='ignore') json_response = json.loads(json_query) if json_response.has_key('result'): if json_response['result'].has_key('value'): return json_response['result']['value'] else: raise SyntaxError('Bad JSON') else: raise SyntaxError('Bad JSON')
# # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import xbmcaddon from resources.lib import taskdict from resources.lib.events import Events from resources.lib.events import requires_subtopic from resources.lib.kodilogging import KodiLogger from resources.lib.pubsub import Topic from resources.lib.utils.kodipathtools import translatepath from resources.lib.utils.poutil import PoDict podict = PoDict() podict.read_from_file(translatepath('special://addon/resources/language/English/strings.po')) def getEnglishStringFromId(msgctxt): status, ret = podict.has_msgctxt(msgctxt) if status is True: return ret else: return '' _ = getEnglishStringFromId try: addonid = xbmcaddon.Addon('script.service.kodi.callbacks').getAddonInfo('id') except RuntimeError:
def testGHA_Detect(): assert UpdateAddon.isGitHubArchive(translatepath('special://addon')) is False assert UpdateAddon.isGitHubArchive(r'C:\Temp\script.service.kodi.callbacks-master') is True
def testGHA_Detect(): assert UpdateAddon.isGitHubArchive( translatepath('special://addon')) is False assert UpdateAddon.isGitHubArchive( r'C:\Temp\script.service.kodi.callbacks-master') is True