def run(self): """ run is the main function managing the key value store. When called, it takes in user input, which it uses to exit the program, save, or undo the changes made. run also handles the modifications to the key value store itself as run is where the changes from insert, delete, and update are made to the running key store. Additionally, the variables necessary to allow for saving and undoing changes are maintained here. Finally, if the program is exited with exit or quit changes are saved to file. No keyword arguments or return value. """ # This section handles user input and passes it to # the handleInput function to change the key value # store. toSave = True while True: n = input("Now we can do awesome stuff! You can exit the program " "with exit or quit if you" " want your changes saved, or with abort if you don't. " "You can also save your changes with save and undo" " them with undo! \n") # Handle exiting the program here if n == "quit" or n == "abort" or n == "exit": if n == "abort": toSave = False break if len(n) == 0: continue # Handle saving and undoing changes here if n == "save": self.invokeSave() self.reset() self.isNewDBFile = False continue elif n == "undo": self.invokeUndo() self.reset() continue else: # handle input here handleValue = self.handleInput(n.lower()) # Check the type of return value. If the value is of type # None, the key value store is to be updated. The actual # renaming, insertion, deletion, and updating happens here. if handleValue is not None: if type(handleValue) == renamed: if handleValue.original is not None: self.handleRenamed(handleValue) elif type(handleValue) == Insert: newRow = handleValue.handleInserts(self.dynamicDB) # We keep track of all row that have been inserted since # the last save/undo or loading the program to either # write them to the file or to reverse these changes. self.insertedRows.update(newRow) self.dynamicDB.update(newRow) for key in newRow: print("Successfully inserted ", key, ": ", newRow[key]['data'], "\n") elif type(handleValue) == Delete: row = handleValue.handleDeletes(self.dynamicDB) for item in row: self.dynamicDB[item]['isFree'] = 'true' # These are in the storage file, so # we should erase them. if 'position' in self.dynamicDB[item]: self.deletedKeys.append(item) else: # This was a new row, so we do not # want to write this to the file. del self.insertedRows[item] # If there were rows updated, we # want to make sure these aren't # written to the file because they # were deleted. if item in self.updatedRows: del self.updatedRows[item] print("Successfully deleted ", item, ": ", self.dynamicDB[item]['data'], "\n") elif type(handleValue) == Update: updatedRow, replacedRow = handleValue.handleUpdates( self.dynamicDB) if updatedRow is not None and len(updatedRow) > 0: for key in updatedRow: # If this is a new row (inserted after loading # the storage file), then we simply change the # inserted value. if key in self.insertedRows: self.insertedRows[key] = updatedRow[key] else: self.updatedRows.update(updatedRow) if key not in self.replacedRows: self.replacedRows.update(replacedRow) print("Successfully updated ", key, ": ", self.dynamicDB[key]['data'], "\n") # If the user specified to exit or quit, we save the changes. We don't # use invokeSave() as that involves unnecessary updating. if toSave: OutputFile.saveChanges(self.isNewDBFile, self.storageFile, self.dynamicDB, self.deletedKeys, self.insertedRows, self.updatedRows, self.maximumPosition)