def test_search_populated(self): @route.Route.register def results(_, search_query): self.assertEqual(search_query, "Rock") yield Listitem.from_dict(results, "listitem one") yield Listitem.from_dict(results, "listitem two") params = dict(_route=results.route.path) session_id = hash_params(params) with storage.PersistentDict(search.SEARCH_DB) as db: dbstore = db.setdefault(session_id, []) dbstore.append("Pop") db.flush() with testing.mock_keyboard("Rock"): listitems = search.SavedSearches.test(search=True, execute_delayed=True, **params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_id, db) self.assertIn("Rock", db[session_id]) self.assertIn("Pop", db[session_id]) self.assertEqual(len(listitems), 2) self.assertEqual(listitems[0].label, "listitem one") self.assertEqual(listitems[1].label, "listitem two")
def delete_ovpn(*args, **kwargs): ovpnfiles = {} with storage.PersistentDict('vpn') as db: try: ovpnfiles = db['ovpnfiles'] except KeyError: db['ovpnfiles'] = ovpnfiles db.flush() if len(ovpnfiles) == 0: return None configs = [] ovpnfileslist = [] for name, configfilepath in list(ovpnfiles.items()): configs.append(name) ovpnfileslist.append(configfilepath) idx = xbmcgui.Dialog().select( Script.localize(30360), configs) if idx < 0: return '' Script.log('Select: [%s]' % ovpnfileslist[idx]) new_ovpnfiles = {} for name, configfilepath in list(ovpnfiles.items()): if configfilepath != ovpnfileslist[idx]: new_ovpnfiles[name] = configfilepath with storage.PersistentDict('vpn') as db: db['ovpnfiles'] = new_ovpnfiles db.flush()
def import_ovpn(*args, **kwargs): path = xbmcgui.Dialog().browse(1, Script.localize(30342), 'files', mask='.ovpn|.conf', enableMultiple=False) if path and os.path.exists(path) and os.path.isfile(path): Script.log('OpenVPN: Import: [%s]' % path) keyboard = xbmc.Keyboard(default='', heading=Script.localize(30348), hidden=False) keyboard.doModal() if keyboard.isConfirmed() and len(keyboard.getText()) > 0: name = keyboard.getText() ovpnfiles = {} with storage.PersistentDict('vpn') as db: ovpnfiles = db['ovpnfiles'] db.flush() if name in ovpnfiles and not xbmcgui.Dialog().yesno( 'OpenVPN', Script.localize(30349)): xbmcgui.Dialog().ok('OpenVPN', Script.localize(30350)) else: ovpnfiles[name] = path with storage.PersistentDict('vpn') as db: db['ovpnfiles'] = ovpnfiles db.flush() else: xbmcgui.Dialog().ok('OpenVPN', Script.localize(30351))
def test_saved_remove(self): # noinspection PyUnusedLocal @route.Route.register def results(_, search_query): pass params = dict(_route=results.route.path) session_id = hash_params(params) with storage.PersistentDict(search.SEARCH_DB) as db: dbstore = db.setdefault(session_id, []) dbstore.append("Rock") dbstore.append("Pop") db.flush() listitems = search.SavedSearches.test(remove_entry="Rock", execute_delayed=True, **params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_id, db) self.assertNotIn("Rock", db[session_id]) self.assertIn("Pop", db[session_id]) self.assertEqual(len(listitems), 2) self.assertIn("Search", listitems[0].label) self.assertEqual(listitems[1].label, "Pop")
def test_saved_not_firstload(self): # noinspection PyUnusedLocal @route.Route.register def results(_, search_query): pass params = dict(_route=results.route.path) session_id = hash_params(params) with storage.PersistentDict(search.SEARCH_DB) as db: dbstore = db.setdefault(session_id, []) dbstore.append("Rock") dbstore.append("Pop") db.flush() with testing.mock_keyboard("Rock"): listitems = search.saved_searches.test(execute_delayed=True, **params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_id, db) self.assertIn("Rock", db[session_id]) self.assertIn("Pop", db[session_id]) self.assertEqual(len(listitems), 3) self.assertIn("Search", listitems[0].label) self.assertEqual(listitems[1].label, "Rock") self.assertEqual(listitems[2].label, "Pop")
def test_persistents(self): with storage.PersistentDict(self.filename) as db: db["persistent"] = "true" self.assertIn("persistent", db) with storage.PersistentDict(self.filename) as db: self.assertIn("persistent", db) self.assertEqual(db["persistent"], "true")
def test_ttl(self): with open(self.path, "wb") as db: pickle.dump({"one": 1, "two": 2}, db, protocol=2) with storage.PersistentDict(self.filename) as db: self.assertIn("one", db) self.assertIn("two", db) time.sleep(2) with storage.PersistentDict(self.filename, 1) as db: self.assertNotIn("one", db) self.assertNotIn("two", db)
def test_version_convert(self): with open(self.path, "wb") as db: pickle.dump({"one": 1, "two": 2}, db, protocol=2) with storage.PersistentDict(self.filename) as db: self.assertIn("one", db) self.assertIn("two", db)
def select_ovpn(): ovpnfiles = {} with storage.PersistentDict('vpn') as db: try: ovpnfiles = db['ovpnfiles'] except KeyError: db['ovpnfiles'] = ovpnfiles db.flush() if len(ovpnfiles) == 0: return None configs = [] ovpnfileslist = [] for name, configfilepath in list(ovpnfiles.items()): configs.append(name) ovpnfileslist.append(configfilepath) idx = xbmcgui.Dialog().select( Script.localize(30352), configs) if idx < 0: return '' Script.log('OpenVPN: Select conf: [%s]' % ovpnfileslist[idx]) return ovpnfileslist[idx]
def move_favourite_item(plugin, direction, item_hash): """ Callback function called when the user click on 'Move up/down' from a favourite item context menu """ if direction == 'down': offset = 1 elif direction == 'up': offset = -1 with storage.PersistentDict("favourites.pickle") as db: item_to_move_id = item_hash item_to_move_order = db[item_hash]['params']['order'] menu = [] for item_hash, item_dict in db.items(): item = (item_dict['params']['order'], item_hash, item_dict) menu.append(item) menu = sorted(menu, key=lambda x: x[0]) for k in range(0, len(menu)): item = menu[k] item_hash = item[1] if item_to_move_id == item_hash: item_to_swap = menu[k + offset] item_to_swap_order = item_to_swap[0] item_to_swap_id = item_to_swap[1] db[item_to_move_id]['params']['order'] = item_to_swap_order db[item_to_swap_id]['params']['order'] = item_to_move_order xbmc.executebuiltin('XBMC.Container.Refresh()') break return False
def migrate_from_pickled_fav(): """ This function moves existing pickled favourites in the new json file used for the favourites. The new format (json) appeared in 0.2.17~beta04 All user with version >= 0.2.17 will use favourites in the JSON format Maybe we can remove the migration check on version 0.2.20? """ # Move all pickled existing favs in json file fav_pickle_fp = os.path.join(Script.get_info('profile'), "favourites.pickle") if xbmcvfs.exists(fav_pickle_fp): Script.log('Start favourites migration from pickle file to json file') new_fav_dict = {} with storage.PersistentDict("favourites.pickle") as db: new_fav_dict = dict(db) # Fix old fav for item_hash, item_dict in new_fav_dict.items(): if 'params' in item_dict and isinstance(item_dict['params'], listing.Params): new_fav_dict[item_hash]['params'] = dict(new_fav_dict[item_hash]['params']) try: del new_fav_dict[item_hash]['params']['item_dict']['params'] except Exception: pass if 'properties' in item_dict: if isinstance(item_dict['properties'], listing.Property): new_fav_dict[item_hash]['properties'] = dict(new_fav_dict[item_hash]['properties']) fav_json_fp = os.path.join(Script.get_info('profile'), "favourites.json") with open(fav_json_fp, 'w') as f: json.dump(new_fav_dict, f, indent=4) xbmcvfs.delete(fav_pickle_fp)
def select_ovpn(): ovpnfiles = {} with storage.PersistentDict('vpn') as db: try: ovpnfiles = db['ovpnfiles'] except KeyError: db['ovpnfiles'] = ovpnfiles db.flush() if len(ovpnfiles) == 0: return None else: response = vpnlib.is_running(ip, port) Script.log('OpenVPN: Response from is_running: [%s] [%s] [%s]' % (response[0], response[1], response[2])) if response[0]: # Le VPN est connecté disconnect_openvpn() configs = [] ovpnfileslist = [] for name, configfilepath in list(ovpnfiles.items()): configs.append(name) ovpnfileslist.append(configfilepath) idx = xbmcgui.Dialog().select( Script.localize(LABELS['Select OpenVPN configuration to run']), configs) if idx >= 0: Script.log('OpenVPN: Select conf: [%s]' % ovpnfileslist[idx]) return ovpnfileslist[idx] else: return ''
def connect_openvpn(config, restart=False, sudopassword=None): with storage.PersistentDict('vpn') as db: Script.log('OpenVPN: Connecting OpenVPN configuration: [%s]' % config) if Script.setting.get_boolean('vpn.sudo') and \ Script.setting.get_boolean('vpn.sudopsw') and sudopassword is None: keyboard = xbmc.Keyboard(default='', heading=Script.localize( LABELS['Enter your sudo password']), hidden=True) keyboard.doModal() if keyboard.isConfirmed(): sudopassword = keyboard.getText() openvpn = vpnlib.OpenVPN( Script.setting.get_string('vpn.openvpnfilepath'), config, ip=ip, port=port, args=Script.setting.get_string('vpn.args'), sudo=Script.setting.get_boolean('vpn.sudo'), sudopwd=sudopassword, debug=True) try: if restart: openvpn.disconnect() db['status'] = "disconnected" openvpn.connect() utils.send_notification(Script.localize( LABELS['Started VPN connection']), title="OpenVPN", time=3000) db['status'] = "connected" except vpnlib.OpenVPNError as exception: if exception.errno == 1: db['status'] = "connected" if xbmcgui.Dialog().yesno( 'OpenVPN', Script.localize(LABELS[ 'An existing OpenVPN instance appears to be running.'] ), Script.localize(LABELS['Disconnect it?'])): Script.log('OpenVPN: User has decided to restart OpenVPN') connect_openvpn(config, True, sudopassword) else: Script.log( 'OpenVPN: User has decided not to restart OpenVPN') else: xbmcgui.Dialog().ok( 'OpenVPN', Script.localize(LABELS[ 'An error has occurred whilst trying to connect OpenVPN'] )) db['status'] = "failed" db.flush()
def test_iter(self): with storage.PersistentDict(self.filename) as db: db.update({"one": 1, "two": 2}) data = list(iter(db)) self.assertEqual(len(data), 2) self.assertIn("one", data) self.assertIn("two", data)
def test_items(self): with storage.PersistentDict(self.filename) as db: db.update({"one": 1, "two": 2}) data = list(db.items()) self.assertEqual(len(data), 2) expected = [("one", 1), ("two", 2)] for item in data: self.assertIn(item, expected)
def test_saved_sessions(self): # noinspection PyUnusedLocal @route.Route.register def session_one(_, search_query): self.assertEqual(search_query, "Rock") yield Listitem.from_dict(session_one, "listitem one") yield Listitem.from_dict(session_one, "listitem two") # noinspection PyUnusedLocal @route.Route.register def session_two(_, search_query): self.assertEqual(search_query, "Pop") yield Listitem.from_dict(session_two, "listitem one") yield Listitem.from_dict(session_two, "listitem two") session_one_params = dict(_route=session_one.route.path) session_one_id = hash_params(session_one_params) session_two_params = dict(_route=session_two.route.path) session_two_id = hash_params(session_two_params) with storage.PersistentDict(search.SEARCH_DB) as db: dbstore = db.setdefault(session_one_id, []) dbstore.append("Jazz") dbstore = db.setdefault(session_two_id, []) dbstore.append("Chill") db.flush() with testing.mock_keyboard("Rock"): search.SavedSearches.test(search=True, execute_delayed=True, **session_one_params) with testing.mock_keyboard("Pop"): search.SavedSearches.test(search=True, execute_delayed=True, **session_two_params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_one_id, db) self.assertIn("Rock", db[session_one_id]) self.assertNotIn("Pop", db[session_one_id]) self.assertIn(session_two_id, db) self.assertIn("Pop", db[session_two_id]) self.assertNotIn("Rock", db[session_two_id])
def import_ovpn(*args, **kwargs): path = xbmcgui.Dialog().browse( 1, Script.localize(LABELS['Import OpenVPN configuration file']), 'files', mask='.ovpn|.conf', enableMultiple=False) if path and os.path.exists(path) and os.path.isfile(path): Script.log('OpenVPN: Import: [%s]' % path) keyboard = xbmc.Keyboard( default='', heading=Script.localize( LABELS['Choose a name for OpenVPN configuration']), hidden=False) keyboard.doModal() if keyboard.isConfirmed() and len(keyboard.getText()) > 0: name = keyboard.getText() ovpnfiles = {} with storage.PersistentDict('vpn') as db: ovpnfiles = db['ovpnfiles'] db.flush() if name in ovpnfiles and not xbmcgui.Dialog().yesno( 'OpenVPN', Script.localize(LABELS[ 'This OpenVPN configuration name already exists. Overwrite?'] )): xbmcgui.Dialog().ok( 'OpenVPN', Script.localize(LABELS['Import cancelled'])) else: ovpnfiles[name] = path with storage.PersistentDict('vpn') as db: db['ovpnfiles'] = ovpnfiles db.flush() else: xbmcgui.Dialog().ok( 'OpenVPN', Script.localize(LABELS[ 'Import failed. You must specify a name for the OpenVPN configuration'] ))
def connect_openvpn(config, restart=False, sudopassword=None): with storage.PersistentDict('vpn') as db: Script.log('OpenVPN: Connecting OpenVPN configuration: [%s]' % config) if Script.setting.get_boolean('vpn.sudo') and \ Script.setting.get_boolean('vpn.sudopsw') and sudopassword is None: keyboard = xbmc.Keyboard(default='', heading=Script.localize(30353), hidden=True) keyboard.doModal() if keyboard.isConfirmed(): sudopassword = keyboard.getText() openvpn = vpnlib.OpenVPN( Script.setting.get_string('vpn.openvpnfilepath'), config, ip=ip, port=port, args=Script.setting.get_string('vpn.args'), sudo=Script.setting.get_boolean('vpn.sudo'), sudopwd=sudopassword, debug=True) try: if restart: openvpn.disconnect() db['status'] = "disconnected" openvpn.connect() Script.notify( "OpenVPN", Script.localize(30354), display_time=3000) db['status'] = "connected" except vpnlib.OpenVPNError as exception: if exception.errno == 1: db['status'] = "connected" if xbmcgui.Dialog().yesno( 'OpenVPN', Script.localize(30356), Script.localize(30357)): Script.log('OpenVPN: User has decided to restart OpenVPN') connect_openvpn(config, True, sudopassword) else: Script.log( 'OpenVPN: User has decided not to restart OpenVPN') else: xbmcgui.Dialog().ok( 'OpenVPN', Script.localize(30358)) db['status'] = "failed" db.flush()
def add_vpn_context(item): with storage.PersistentDict('vpn') as db: vpn_label = Script.localize(LABELS['Connect VPN']) if 'status' in db: if db['status'] == 'connected': vpn_label = Script.localize(LABELS['Disconnect VPN']) else: db['status'] = 'disconnected' db.flush() item.context.script(vpn_item_callback, vpn_label)
def delete_ovpn(*args, **kwargs): ovpnfiles = {} with storage.PersistentDict('vpn') as db: try: ovpnfiles = db['ovpnfiles'] except KeyError: db['ovpnfiles'] = ovpnfiles db.flush() if len(ovpnfiles) == 0: return None else: response = vpnlib.is_running(ip, port) Script.log('OpenVPN: Response from is_running: [%s] [%s] [%s]' % (response[0], response[1], response[2])) if response[0]: # Le VPN est connecté Script.log('OpenVPN: VPN still connected, we disconnect it') disconnect_openvpn() configs = [] ovpnfileslist = [] for name, configfilepath in list(ovpnfiles.items()): configs.append(name) ovpnfileslist.append(configfilepath) idx = xbmcgui.Dialog().select( Script.localize(LABELS['Select OpenVPN configuration to delete']), configs) if idx >= 0: Script.log('Select: [%s]' % ovpnfileslist[idx]) new_ovpnfiles = {} for name, configfilepath in list(ovpnfiles.items()): if configfilepath != ovpnfileslist[idx]: new_ovpnfiles[name] = configfilepath with storage.PersistentDict('vpn') as db: db['ovpnfiles'] = new_ovpnfiles db.flush() else: return ''
def rename_favourite_item(plugin, item_hash): """ Callback function called when the user click on 'rename' from a favourite item context menu """ item_label = utils.keyboard(plugin.localize(LABELS['Favorite name']), xbmc.getInfoLabel('ListItem.Label')) # If user aborded do not edit this item if item_label == '': return False with storage.PersistentDict("favourites.pickle") as db: db[item_hash]['label'] = item_label xbmc.executebuiltin('XBMC.Container.Refresh()')
def disconnect_openvpn(): with storage.PersistentDict('vpn') as db: Script.log('OpenVPN: Disconnecting OpenVPN') try: db['status'] = "disconnecting" response = vpnlib.is_running(ip, port) if response[0]: vpnlib.disconnect(ip, port) if response[1] is not None: Script.notify('OpenVPN', Script.localize(30355)) db['status'] = "disconnected" Script.log('OpenVPN: Disconnect OpenVPN successful') except vpnlib.OpenVPNError as exception: xbmcgui.Dialog().ok('OpenVPN', Script.localize(30358)) Script.log('OpenVPN: OpenVPN error: ' + str(exception)) db['status'] = "failed" db.flush()
def test_first_load_canceled(self): # noinspection PyUnusedLocal @route.Route.register def results(_, search_query): pass params = dict(_route=results.route.path) session_id = hash_params(params) with testing.mock_keyboard(""): listitems = search.SavedSearches.test(first_load=True, execute_delayed=True, **params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_id, db) self.assertFalse(bool(db[session_id])) self.assertFalse(listitems)
def test_first_load_invalid(self): @route.Route.register def results(_, search_query): self.assertEqual(search_query, "Rock") return False params = dict(_route=results.route.path) session_id = hash_params(params) with testing.mock_keyboard("Rock"): listitems = search.SavedSearches.test(first_load=True, execute_delayed=True, **params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_id, db) self.assertNotIn("Rock", db[session_id]) self.assertFalse(listitems)
def vpn_item_callback(plugin): with storage.PersistentDict('vpn') as db: if 'status' not in db: db['status'] = "disconnected" elif db['status'] != "connected": ovpn = select_ovpn() if ovpn is None: import_ovpn() # Case when the user cancel the import dialog if ovpn is None: return False if len(ovpn) > 0: connect_openvpn(ovpn) elif db['status'] == "connected": disconnect_openvpn() db.flush() xbmc.executebuiltin('Container.Refresh()')
def test_first_load(self): @route.Route.register def results(_, search_query): self.assertEqual(search_query, "Rock") yield Listitem.from_dict(results, "listitem one") yield Listitem.from_dict(results, "listitem two") params = dict(_route=results.route.path) session_id = hash_params(params) with testing.mock_keyboard("Rock"): listitems = search.saved_searches.test(first_load=True, execute_delayed=True, **params) with storage.PersistentDict(search.SEARCH_DB) as db: self.assertIn(session_id, db) self.assertIn("Rock", db[session_id]) self.assertEqual(len(listitems), 2) self.assertEqual(listitems[0].label, "listitem one") self.assertEqual(listitems[1].label, "listitem two")
def add_context_menus_to_item(plugin, item, index, item_id, menu_id, menu_len): # Move up if index > 0: item.context.script(move_item, plugin.localize(LABELS['Move up']), direction='up', item_id=item_id, menu_id=menu_id) # Move down if index < menu_len - 1: item.context.script(move_item, plugin.localize(LABELS['Move down']), direction='down', item_id=item_id, menu_id=menu_id) # Hide item.context.script(hide_item, plugin.localize(LABELS['Hide']), item_id=item_id) # Connect/Disconnect VPN with storage.PersistentDict('vpn') as db: vpn_label = plugin.localize(LABELS['Connect VPN']) if 'status' in db: if db['status'] == 'connected': vpn_label = plugin.localize(LABELS['Disconnect VPN']) else: db['status'] = 'disconnected' db.flush() item.context.script(vpn.vpn_item_callback, vpn_label) return
def remove_favourite_item(plugin, item_hash): """ Callback function called when the user click on 'remove' from a favourite item context menu """ with storage.PersistentDict("favourites.pickle") as db: del db[item_hash] # We need to fix the order param # in order to not break the move up/down action menu = [] for item_hash, item_dict in db.items(): item = (item_dict['params']['order'], item_hash) menu.append(item) menu = sorted(menu, key=lambda x: x[0]) for k in range(0, len(menu)): item = menu[k] item_hash = item[1] db[item_hash]['params']['order'] = k xbmc.executebuiltin('XBMC.Container.Refresh()')
def test_del(self): with storage.PersistentDict(self.filename) as db: db.update({"one": 1, "two": 2}) del db["one"] self.assertNotIn("one", db) self.assertIn("two", db)
def test_len(self): with storage.PersistentDict(self.filename) as db: db.update({"one": 1, "two": 2}) self.assertEqual(len(db), 2)