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 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 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)
Example #9
0
 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
Example #13
0
 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)
Example #14
0
 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()
Example #17
0
 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 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 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
Example #25
0
    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')
Example #28
0
 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)
Example #30
0
        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
Example #31
0
#    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')
                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:
#
#    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