def load_from(self, filename=None): """Start with a blank in memory registry, and load from the given filename""" if filename == None: filename = DeviceRegistry.DEFAULT_FILENAME # Create a new in memory store, effectively removing any existing in memory device class instances #TODO: Not good if there are routes to those class instances? self.store = KVS(filename) #TODO: later we might make it possible to load_from multiple files self.store.load(filename, Devices.DeviceFactory.get_device_from_name)
def test_keys(self): """Get out all keys of the kvs""" kvs = KVS() kvs["tv1"] = TV(1) kvs["tv2"] = TV(2) kvs["tv3"] = TV(3) print(kvs.keys())
def test_write(self): """Write an in memory KVS to a file""" remove_file(self.KVS_FILENAME) kvs = KVS() kvs["tv1"] = TV(1) kvs.write(self.KVS_FILENAME) show_file(self.KVS_FILENAME)
def __init__(self): self.api = SublimeSocketAPI(self) self.kvs = KVS() self.transfer = None self.reserveRestart = None self.onConnectedTriggers = []
def test_ADD_factory(self): #NOTE: This is an under the bonnet test of parsing an ADD record from the file obj = {"type": "TV", "id": 1234} kvs = KVS(self.KVS_FILENAME) kvs.ADD("tv1", obj, create_fn=FACTORY.get) # expected result: object described as a kvp becomes a configured object instance in store print(kvs.store)
def test_IGN(self): #NOTE: This is an under the bonnet test of parsing an IGN record from the file obj = {"type": "TV", "id": 1234} kvs = KVS(self.KVS_FILENAME) kvs.IGN("tv1", obj) # expected result: no change to the in memory data structures print(kvs.store)
def test_ADD_nofactory(self): #NOTE: This is an under the bonnet test of parsing an ADD record from the file # No factory callback provided, use ADD parse action obj = {"type": "MIHO005", "id": 1234} kvs = KVS(self.KVS_FILENAME) kvs.ADD("tv1", obj) # expected result: object described as a kvp becomes a kvp in the store if no factory callback print(kvs.store)
def test_size(self): """How big is the kvs""" kvs = KVS() kvs["tv1"] = TV(1) print(len(kvs)) kvs["tv2"] = TV(2) print(len(kvs))
def test_change(self): """Change the value associated with an existing key""" kvs = KVS() kvs["tv1"] = TV(1) kvs["tv1"] = TV(111) # change it print(kvs.store)
def test_add(self): """Add an object into the kvs store""" kvs = KVS() kvs["tv1"] = TV(1) kvs["tv2"] = TV(2) print(kvs.store)
def test_add(self): """Add a new record to a persisted KVS""" remove_file(self.KVS_FILENAME) kvs = KVS(self.KVS_FILENAME) kvs["tv1"] = TV(1) print(kvs.store) show_file(self.KVS_FILENAME)
def test_change(self): """Change an existing record in a persisted KVS""" remove_file(self.KVS_FILENAME) kvs = KVS(self.KVS_FILENAME) kvs["tv1"] = TV(1) show_file(self.KVS_FILENAME) kvs["tv1"] = TV(2) show_file(self.KVS_FILENAME)
def test_DEL(self): #NOTE: This is an under the bonnet test of parsing a DEL record from the file #NOTE: This is an under the bonnet test of parsing an IGN record from the file obj = {"type": "TV", "id": 1234} kvs = KVS(self.KVS_FILENAME) kvs.ADD("tv1", obj) kvs.DEL("tv1", obj) # expected result: record is deleted from in memory store print(kvs.store) try: kvs.DEL("tv1", obj) self.fail("Did not get expected KeyError") except KeyError: pass # expected # expected result: error if it was not in the store in the first place print(kvs.store)
def test_delete(self): """Delete an existing key in the store, and a missing key for error""" kvs = KVS() kvs["tv1"] = TV(1) del kvs["tv1"] print(kvs.store) try: del kvs["tv1"] # expect error self.fail("Did not get expected KeyError exception") except KeyError: pass # expected
def test_not_persistable(self): class NPC(): pass remove_file(self.KVS_FILENAME) kvs = KVS(self.KVS_FILENAME) try: kvs["npc"] = NPC() # should throw NotPersistableError self.fail("Did not get expected NotPersistableError") except NotPersistableError: pass # expected
def test_load_process(self): """Load and process a file with lots of records in it""" CONTENTS = """\ ADD tv type=TV id=1 IGN fan type=TV id=2 DEL tv ADD fridge type=TV id=99 """ write_file(self.KVS_FILENAME, CONTENTS) kvs = KVS(self.KVS_FILENAME) kvs.load(create_fn=FACTORY.get) print(kvs.store)
def test_delete(self): """Delete an existing key from the persistent version""" remove_file(self.KVS_FILENAME) kvs = KVS(self.KVS_FILENAME) kvs["tv1"] = TV(1) kvs["tv2"] = TV(2) kvs["tv3"] = TV(3) kvs["tv4"] = TV(4) show_file(self.KVS_FILENAME) del kvs["tv1"]
def test_load_cache(self): """Load record from a kvs file into the kvs cache""" # create a file to test against remove_file(self.KVS_FILENAME) kvs = KVS() kvs["tv1"] = TV(1) kvs.write(self.KVS_FILENAME) kvs = KVS() # clear it out again # load the file kvs.load(self.KVS_FILENAME) # check the state of the kvs memory print(kvs.store) # check state of the kvs file at end show_file(self.KVS_FILENAME)
################### #preparation phase# ################### with open('config.json') as d: config = json.load(d) #Total number of servers n_servers = config["servers"] #Total number of tolerated failures f_servers = (n_servers - 1) / 3 kvsArray = {} for i in range(0, n_servers): c = config['KVS_IPs'][i] kvsArray[i] = KVS(c['ip'], c['port']) ################## # API # ################## #write method - writes the value under the key in a majority (2*f+1) of the KVS #in order to provide fault tolerance def write(key, value): responses = 0 i = 0 while responses < (f_servers * 2 + 1) and i < n_servers: try: kvsArray[i].write(key, value)
def test_get(self): """Get the object associated with a key in the store""" kvs = KVS() kvs["tv1"] = TV(1) t = kvs["tv1"] print(t)
class DeviceRegistry(): # this is actions, so is this the 'RegistRAR'?? """A persistent registry for device class instance configurations""" DEFAULT_FILENAME = "registry.kvs" def __init__(self, filename=None): ##print("***Opening DeviceRegistry") self.store = KVS(filename) self.fsk_router = None def set_fsk_router(self, fsk_router): self.fsk_router = fsk_router def load_from(self, filename=None): """Start with a blank in memory registry, and load from the given filename""" if filename == None: filename = DeviceRegistry.DEFAULT_FILENAME # Create a new in memory store, effectively removing any existing in memory device class instances #TODO: Not good if there are routes to those class instances? self.store = KVS(filename) #TODO: later we might make it possible to load_from multiple files self.store.load(filename, Devices.DeviceFactory.get_device_from_name) def load_into(self, context): """auto-create variables in the provided context, for all persisted registry entries""" if context == None: raise ValueError("Must provide a context to hold new variables") for name in self.store.keys(): c = self.get(name) # This creates a variable inside the context of this name, points to class instance setattr(context, name, c) def add(self, device, name): """Add a device class instance to the registry, with a friendly name""" self.store[name] = device def get(self, name): # -> Device """Get the description for a device class from the store, and construct a class instance""" c = self.store[name] if self.fsk_router != None: if c.can_send(): # if can transmit, we can receive from it if isinstance(c, Devices.MiHomeDevice): print("Adding rx route for transmit enabled device %s" % c) address = (c.manufacturer_id, c.product_id, c.device_id) self.fsk_router.add(address, c) return c def rename(self, old_name, new_name): """Rename a device in the registry""" c = self.store[old_name] # get the class instance self.delete(old_name) # remove from memory and from any disk version self.add(c, new_name) # Add the same class back, but with the new name #Note: If rx routes are defined, they will still be correct, # because they wire directly to the device class instance def delete(self, name): """Delete the named class instance""" del self.store[name] def list(self): """List the registry in a vaguely printable format, mostly for debug""" print("REGISTERED DEVICES:") for k in self.store.keys(): print(" %s -> %s" % (k, self.store[k])) def size(self): """How many entries are there in the registry?""" return self.store.size() def devices(self): """A generator/iterator that can be used to get a list of device instances""" # Python2 and Python3 safe for k in self.store.keys(): device = self.store[k] yield device # first get a list of all devices, in case the registry changes while iterating ##devices = self.store.keys() # now 'generate' one per call ##i = 0 ##while i < len(devices): ## k = devices[i] ## device = self.store[k] ## yield device ## i += 1 def names(self): """A generator/iterator that can be used to get a list of device names""" # first get a list of all devices, in case the registry changes while iterating devices = list(self.store.keys()) # now 'generate' one per call i = 0 while i < len(devices): k = devices[i] yield k i += 1
def __init__(self, filename=None): ##print("***Opening DeviceRegistry") self.store = KVS(filename) self.fsk_router = None
def test_create_blank(self): """Create a blank kvs, not bound to any external file""" kvs = KVS()
class SublimeSocketServer: def __init__(self): self.api = SublimeSocketAPI(self) self.kvs = KVS() self.transfer = None self.reserveRestart = None self.onConnectedTriggers = [] # control server self. def resetServer(self): self.refreshKVS() self.teardownTransfer() def teardownServer(self): self.resetServer() # teardowned will call. def refreshKVS(self): self.clearAllKeysAndValues() def transferTeardowned(self, message): self.api.editorAPI.printMessage(message + "\n") self.api.editorAPI.statusMessage(message) self.transfer = None # run when restert reserved. if self.reserveRestart: self.setupTransfer(*self.reserveRestart) self.spinupTransfer() self.reserveRestart = None def transferNoticed(self, message): self.api.editorAPI.printMessage(message) def transferSpinupFailed(self, message): self.api.editorAPI.printMessage(message) self.api.editorAPI.statusMessage(message) def transferSpinupped(self, message): self.api.editorAPI.printMessage(message) self.api.editorAPI.statusMessage(message) # react to renew self.onTransferRenew() def transferConnected(self, clientId): if self.onConnectedTriggers: for funcDict in self.onConnectedTriggers: for _, func in funcDict.items(): func() self.onConnectedTriggers = [] # main API data incoming method. def transferInputted(self, data, clientId): apiData = data.split(SublimeSocketAPISettings.SSAPI_DEFINE_DELIM, 1)[1] def runInMainThread(): self.api.parse(apiData, clientId) self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0) def showTransferInfo(self): if self.transfer: return self.transfer.info() else: return "no transfer running." # control transfer. def setupTransfer(self, transferMethod, params): if self.transfer: message = "SublimeSocket already running." + self.transfer.info() self.api.editorAPI.printMessage(message + "\n") self.api.editorAPI.statusMessage(message) else: if transferMethod in SublimeSocketAPISettings.TRANSFER_METHODS: for case in PythonSwitch(transferMethod): if case(SublimeSocketAPISettings.WEBSOCKET_SERVER): self.transfer = WSServer(self) self.transfer.setup(params) break self.currentTransferMethod = transferMethod def spinupTransfer(self): if self.transfer: self.transfer.spinup() def restartTransfer(self): if self.transfer: # reserve restart self.reserveRestart = self.transfer.currentArgs() self.teardownTransfer() else: self.transferSpinupFailed("no transfer running.") def teardownTransfer(self): if self.transfer: self.transfer.teardown() else: self.transferTeardowned("no transfer running.") def appendOnConnectedTriggers(self, func): for addedFunctionDict in self.onConnectedTriggers: if func.__name__ in addedFunctionDict.keys(): print("duplicate trigger:" + str(func)) return self.onConnectedTriggers.append({func.__name__: func}) # message series def sendMessage(self, targetId, message): return self.transfer.sendMessage(targetId, message) def broadcastMessage(self, targetIds, message): return self.transfer.broadcastMessage(targetIds, message) # purge def purgeConnection(self, targetId): self.transfer.purgeConnection(targetId) # other series def onTransferRenew(self): def runInMainThread(): settingCommands = self.api.editorAPI.loadSettings( "onTransferRenew") for command in settingCommands: self.api.runAPI(command, None) self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0) # KVS bridge series def clearAllKeysAndValues(self): self.kvs.clear() def showAllKeysAndValues(self): everything = self.kvs.getAll() print("everything", everything) # views and KVS def viewsDict(self): viewsDict = self.kvs.get(SublimeSocketAPISettings.DICT_VIEWS) if viewsDict: return viewsDict return {} def updateViewsDict(self, viewsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_VIEWS, viewsDict) # regions and KVS def storeRegion(self, path, identity, line, regionFrom, regionTo, message): regionsDict = self.regionsDict() if path in regionsDict: if identity in regionsDict[path]: pass else: regionsDict[path][identity] = {} regionsDict[path][identity][ SublimeSocketAPISettings.REGION_LINE] = line regionsDict[path][identity][ SublimeSocketAPISettings.REGION_FROM] = regionFrom regionsDict[path][identity][ SublimeSocketAPISettings.REGION_TO] = regionTo regionsDict[path][identity][ SublimeSocketAPISettings.REGION_MESSAGES] = [] else: regionsDict[path] = {} regionsDict[path][identity] = {} regionsDict[path][identity][ SublimeSocketAPISettings.REGION_LINE] = line regionsDict[path][identity][ SublimeSocketAPISettings.REGION_FROM] = regionFrom regionsDict[path][identity][ SublimeSocketAPISettings.REGION_TO] = regionTo regionsDict[path][identity][ SublimeSocketAPISettings.REGION_MESSAGES] = [] if not message in regionsDict[path][identity][ SublimeSocketAPISettings.REGION_MESSAGES]: regionsDict[path][identity][ SublimeSocketAPISettings.REGION_MESSAGES].insert(0, message) self.updateRegionsDict(regionsDict) def regionsDict(self): regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS) if regionsDict: return regionsDict return {} def updateRegionsDict(self, regionsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REGIONS, regionsDict) def selectingRegionIds(self, path): regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS) if path in regionsDict: selectingRegionIds = [ regionId for regionId, regionDatas in regionsDict[path].items() if SublimeSocketAPISettings.REGION_ISSELECTING in regionDatas and regionDatas[ SublimeSocketAPISettings.REGION_ISSELECTING] == 1 ] return selectingRegionIds return [] def updateSelectingRegionIdsAndResetOthers(self, path, selectingRegionIds): regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS) if path in regionsDict: regions = regionsDict[path] allRegionIds = list(regions) unselectedRegionIds = set(allRegionIds) - set(selectingRegionIds) for selectingRegionId in selectingRegionIds: regions[selectingRegionId][ SublimeSocketAPISettings.REGION_ISSELECTING] = 1 for unselectdRegionid in unselectedRegionIds: regions[unselectdRegionid][ SublimeSocketAPISettings.REGION_ISSELECTING] = 0 # reactor and KVS def reactorsDict(self): reactorsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REACTORS) if reactorsDict: return reactorsDict return {} def updateReactorsDict(self, reactorsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORS, reactorsDict) # reactorsLog and KVS def reactorsLogDict(self): reactorsLogDict = self.kvs.get( SublimeSocketAPISettings.DICT_REACTORSLOG) if reactorsLogDict: return reactorsLogDict return {} def updateReactorsLogDict(self, reactorsLogDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORSLOG, reactorsLogDict) # completions and KVS def completionsDict(self): completionsDict = self.kvs.get( SublimeSocketAPISettings.DICT_COMPLETIONS) if completionsDict: return completionsDict return {} def deleteCompletion(self, identity): completionsDict = self.kvs.get( SublimeSocketAPISettings.DICT_COMPLETIONS) del completionsDict[identity] self.updateCompletionsDict(completionsDict) def updateCompletionsDict(self, completionsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_COMPLETIONS, completionsDict) # filters and KVS def filtersDict(self): filtersDict = self.kvs.get(SublimeSocketAPISettings.DICT_FILTERS) if filtersDict: return filtersDict return {} def updateFiltersDict(self, filtersDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_FILTERS, filtersDict)
class DeviceRegistry(): # this is actions, so is this the 'RegistRAR'?? """A persistent registry for device class instance configurations""" DEFAULT_FILENAME = "registry.kvs" def __init__(self, filename=None): ##print("***Opening DeviceRegistry") self.store = KVS(filename) self.fsk_router = None def set_fsk_router(self, fsk_router): self.fsk_router = fsk_router def load_from(self, filename=None): """Start with a blank in memory registry, and load from the given filename""" if filename == None: filename = DeviceRegistry.DEFAULT_FILENAME # Create a new in memory store, effectively removing any existing in memory device class instances #TODO: Not good if there are routes to those class instances? self.store = KVS( filename ) #TODO: later we might make it possible to load_from multiple files self.store.load(filename, Devices.DeviceFactory.get_device_from_name) def load_into(self, context): """auto-create variables in the provided context, for all persisted registry entries""" if context == None: raise ValueError("Must provide a context to hold new variables") for name in self.store.keys(): c = self.get(name) # This creates a variable inside the context of this name, points to class instance setattr(context, name, c) def add(self, device, name): """Add a device class instance to the registry, with a friendly name""" self.store[name] = device def get(self, name): # -> Device """Get the description for a device class from the store, and construct a class instance""" c = self.store[name] if self.fsk_router != None: if c.can_send(): # if can transmit, we can receive from it if isinstance(c, Devices.MiHomeDevice): #print("Adding rx route for transmit enabled device %s" % c) address = (c.manufacturer_id, c.product_id, c.device_id) self.fsk_router.add(address, c) return c def rename(self, old_name, new_name): """Rename a device in the registry""" c = self.store[old_name] # get the class instance self.delete(old_name) # remove from memory and from any disk version self.add(c, new_name) # Add the same class back, but with the new name #Note: If rx routes are defined, they will still be correct, # because they wire directly to the device class instance def delete(self, name): """Delete the named class instance""" del self.store[name] def list(self): """List the registry in a vaguely printable format, mostly for debug""" print("REGISTERED DEVICES:") for k in self.store.keys(): print(" %s -> %s" % (k, self.store[k])) def size(self): """How many entries are there in the registry?""" return self.store.size() def devices(self): """A generator/iterator that can be used to get a list of device instances""" # Python2 and Python3 safe for k in self.store.keys(): device = self.store[k] yield device # first get a list of all devices, in case the registry changes while iterating ##devices = self.store.keys() # now 'generate' one per call ##i = 0 ##while i < len(devices): ## k = devices[i] ## device = self.store[k] ## yield device ## i += 1 def names(self): """A generator/iterator that can be used to get a list of device names""" # first get a list of all devices, in case the registry changes while iterating devices = list(self.store.keys()) # now 'generate' one per call i = 0 while i < len(devices): k = devices[i] yield k i += 1
class SublimeSocketServer: def __init__(self): self.api = SublimeSocketAPI(self) self.kvs = KVS() self.transfer = None self.reserveRestart = None self.onConnectedTriggers = [] # control server self. def resetServer(self): self.refreshKVS() self.teardownTransfer() def teardownServer(self): self.resetServer() # teardowned will call. def refreshKVS(self): self.clearAllKeysAndValues() def transferTeardowned(self, message): self.api.editorAPI.printMessage(message + "\n") self.api.editorAPI.statusMessage(message) self.transfer = None # run when restert reserved. if self.reserveRestart: self.setupTransfer(*self.reserveRestart) self.spinupTransfer() self.reserveRestart = None def transferNoticed(self, message): self.api.editorAPI.printMessage(message) def transferSpinupFailed(self, message): self.api.editorAPI.printMessage(message) self.api.editorAPI.statusMessage(message) def transferSpinupped(self, message): self.api.editorAPI.printMessage(message) self.api.editorAPI.statusMessage(message) # react to renew self.onTransferRenew() def transferConnected(self, clientId): if self.onConnectedTriggers: for funcDict in self.onConnectedTriggers: for _, func in funcDict.items(): func() self.onConnectedTriggers = [] # main API data incoming method. def transferInputted(self, data, clientId): apiData = data.split(SublimeSocketAPISettings.SSAPI_DEFINE_DELIM, 1)[1] def runInMainThread(): self.api.parse(apiData, clientId) self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0) def showTransferInfo(self): if self.transfer: return self.transfer.info() else: return "no transfer running." # control transfer. def setupTransfer(self, transferMethod, params): if self.transfer: message = "SublimeSocket already running." + self.transfer.info() self.api.editorAPI.printMessage(message + "\n") self.api.editorAPI.statusMessage(message) else: if transferMethod in SublimeSocketAPISettings.TRANSFER_METHODS: for case in PythonSwitch(transferMethod): if case(SublimeSocketAPISettings.WEBSOCKET_SERVER): self.transfer = WSServer(self) self.transfer.setup(params) break self.currentTransferMethod = transferMethod def spinupTransfer(self): if self.transfer: self.transfer.spinup() def restartTransfer(self): if self.transfer: # reserve restart self.reserveRestart = self.transfer.currentArgs() self.teardownTransfer() else: self.transferSpinupFailed("no transfer running.") def teardownTransfer(self): if self.transfer: self.transfer.teardown() else: self.transferTeardowned("no transfer running.") def appendOnConnectedTriggers(self, func): for addedFunctionDict in self.onConnectedTriggers: if func.__name__ in addedFunctionDict.keys(): print("duplicate trigger:"+str(func)) return self.onConnectedTriggers.append({func.__name__:func}) # message series def sendMessage(self, targetId, message): return self.transfer.sendMessage(targetId, message) def broadcastMessage(self, targetIds, message): return self.transfer.broadcastMessage(targetIds, message) # purge def purgeConnection(self, targetId): self.transfer.purgeConnection(targetId) # other series def onTransferRenew(self): def runInMainThread () : settingCommands = self.api.editorAPI.loadSettings("onTransferRenew") for command in settingCommands: self.api.runAPI(command, None) self.api.editorAPI.runAfterDelay(lambda: runInMainThread(), 0) # KVS bridge series def clearAllKeysAndValues(self): self.kvs.clear() def showAllKeysAndValues(self): everything = self.kvs.getAll() print("everything", everything) # views and KVS def viewsDict(self): viewsDict = self.kvs.get(SublimeSocketAPISettings.DICT_VIEWS) if viewsDict: return viewsDict return {} def updateViewsDict(self, viewsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_VIEWS, viewsDict) # regions and KVS def storeRegion(self, path, identity, line, regionFrom, regionTo, message): regionsDict = self.regionsDict() if path in regionsDict: if identity in regionsDict[path]: pass else: regionsDict[path][identity] = {} regionsDict[path][identity][SublimeSocketAPISettings.REGION_LINE] = line regionsDict[path][identity][SublimeSocketAPISettings.REGION_FROM] = regionFrom regionsDict[path][identity][SublimeSocketAPISettings.REGION_TO] = regionTo regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES] = [] else: regionsDict[path] = {} regionsDict[path][identity] = {} regionsDict[path][identity][SublimeSocketAPISettings.REGION_LINE] = line regionsDict[path][identity][SublimeSocketAPISettings.REGION_FROM] = regionFrom regionsDict[path][identity][SublimeSocketAPISettings.REGION_TO] = regionTo regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES] = [] if not message in regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES]: regionsDict[path][identity][SublimeSocketAPISettings.REGION_MESSAGES].insert(0, message) self.updateRegionsDict(regionsDict) def regionsDict(self): regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS) if regionsDict: return regionsDict return {} def updateRegionsDict(self, regionsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REGIONS, regionsDict) def selectingRegionIds(self, path): regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS) if path in regionsDict: selectingRegionIds = [regionId for regionId, regionDatas in regionsDict[path].items() if SublimeSocketAPISettings.REGION_ISSELECTING in regionDatas and regionDatas[SublimeSocketAPISettings.REGION_ISSELECTING] == 1] return selectingRegionIds return [] def updateSelectingRegionIdsAndResetOthers(self, path, selectingRegionIds): regionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REGIONS) if path in regionsDict: regions = regionsDict[path] allRegionIds = list(regions) unselectedRegionIds = set(allRegionIds) - set(selectingRegionIds) for selectingRegionId in selectingRegionIds: regions[selectingRegionId][SublimeSocketAPISettings.REGION_ISSELECTING] = 1 for unselectdRegionid in unselectedRegionIds: regions[unselectdRegionid][SublimeSocketAPISettings.REGION_ISSELECTING] = 0 # reactor and KVS def reactorsDict(self): reactorsDict = self.kvs.get(SublimeSocketAPISettings.DICT_REACTORS) if reactorsDict: return reactorsDict return {} def updateReactorsDict(self, reactorsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORS, reactorsDict) # reactorsLog and KVS def reactorsLogDict(self): reactorsLogDict = self.kvs.get(SublimeSocketAPISettings.DICT_REACTORSLOG) if reactorsLogDict: return reactorsLogDict return {} def updateReactorsLogDict(self, reactorsLogDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_REACTORSLOG, reactorsLogDict) # completions and KVS def completionsDict(self): completionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_COMPLETIONS) if completionsDict: return completionsDict return {} def deleteCompletion(self, identity): completionsDict = self.kvs.get(SublimeSocketAPISettings.DICT_COMPLETIONS) del completionsDict[identity] self.updateCompletionsDict(completionsDict) def updateCompletionsDict(self, completionsDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_COMPLETIONS, completionsDict) # filters and KVS def filtersDict(self): filtersDict = self.kvs.get(SublimeSocketAPISettings.DICT_FILTERS) if filtersDict: return filtersDict return {} def updateFiltersDict(self, filtersDict): self.kvs.setKeyValue(SublimeSocketAPISettings.DICT_FILTERS, filtersDict)