def __init__(self): try: self.aliases = eval(Config.byName("ALIASES").value) except SQLObjectNotFound: self.aliases = {} except Exception: tui.error("Aliases syntax error. Ignored") self.aliases = {}
def __init__(self): try: self.aliases = eval(db.getConfigKey("ALIASES", environ=False)) except NoResultFound: self.aliases = {} except Exception: tui.error("Aliases syntax error. Ignored") self.aliases = {}
def do_a_remove(self, line): """Remove an alias""" if line in self.aliases: del self.aliases[line] aliases = Config.selectBy(name="ALIASES")[0] aliases.value = repr(self.aliases) else: tui.error( "No alias with that name. Use a_list to display all aliases")
def warnIfKeywordDoesNotExist(keywordFilters): """Warn user is keyword does not exist @return: True if at least one keyword does not exist, else False""" doesNotExist = False for keyword in [k.name for k in keywordFilters]: if Keyword.select(LIKE(Keyword.q.name, keyword)).count() == 0: tui.error("Keyword %s is unknown." % keyword) doesNotExist = True return doesNotExist
def processDbPathArg(dbPath, dataDir): if not dbPath: return basepaths.getDbPath(dataDir) dbPath = os.path.abspath(dbPath) dbDir = os.path.dirname(dbPath) tui.warning('--db option is deprecated and will be removed in the next version, use --datadir instead') if not os.path.isdir(dbDir): tui.error("Directory '{}' does not exist".format(dbDir)) sys.exit(1) return dbPath
def do_a_remove(self, line): """Remove an alias""" if line in self.aliases: session = db.getSession() del self.aliases[line] alias = session.query(db.Alias).filter_by(name=line).one() session.delete(alias) session.commit() else: tui.error("No alias with that name. Use a_list to display all aliases")
def processDataDirArg(dataDir): if dataDir: dataDir = os.path.abspath(dataDir) if not os.path.isdir(dataDir): tui.error("Directory '{}' does not exist".format(dataDir)) sys.exit(1) else: dataDir = basepaths.getDataDir() os.makedirs(dataDir, exist_ok=True) return dataDir
def warnIfKeywordDoesNotExist(keywordFilters): """Warn user is keyword does not exist @return: True if at least one keyword does not exist, else False""" session = db.getSession() doesNotExist = False for keyword in [k.name for k in keywordFilters]: if session.query(Keyword).filter(Keyword.name.like(keyword)).count() == 0: tui.error("Keyword %s is unknown." % keyword) doesNotExist = True return doesNotExist
def warnIfKeywordDoesNotExist(keywordFilters): """Warn user is keyword does not exist @return: True if at least one keyword does not exist, else False""" session = db.getSession() doesNotExist = False for keyword in [k.name for k in keywordFilters]: if session.query(Keyword).filter( Keyword.name.like(keyword)).count() == 0: tui.error("Keyword %s is unknown." % keyword) doesNotExist = True return doesNotExist
def do_k_edit(self, line): """Edit a keyword k_edit @<keyword>""" session = db.getSession() keyword = dbutils.getKeywordFromName(line) oldName = keyword.name newName = tui.editLine(oldName) if newName == "": print("Cancelled") return lst = session.query(Keyword).filter_by(name=newName).all() if len(lst) == 0: # Simple case: newName does not exist, just rename the existing keyword keyword.name = newName session.merge(keyword) session.commit() print("Keyword %s has been renamed to %s" % (oldName, newName)) return # We already have a keyword with this name, we need to merge print("Keyword %s already exists" % newName) if not tui.confirm("Do you want to merge %s and %s" % (oldName, newName)): return # Check we can merge conflictingTasks = [] for task in keyword.tasks: kwDict = task.getKeywordDict() if oldName in kwDict and newName in kwDict and kwDict[ oldName] != kwDict[newName]: conflictingTasks.append(task) if len(conflictingTasks) > 0: # We cannot merge tui.error("Cannot merge keywords %s and %s because they are both" " used with different values in these tasks:" % (oldName, newName)) for task in conflictingTasks: print("- %d, %s" % (task.id, task.title)) print("Edit these tasks and try again") return # Merge for task in keyword.tasks: kwDict = task.getKeywordDict() if newName not in kwDict: kwDict[newName] = kwDict[oldName] del kwDict[oldName] task.setKeywordDict(kwDict) session.delete(keyword) session.commit() print("Keyword %s has been merged with %s" % (oldName, newName))
def checkVersion(self): """Check version and exit if it is not suitable""" version = self.getVersion() if version != DB_VERSION: sharePath = os.path.abspath(utils.shareDirPath()) tui.error("Your database version is %d but Yokadi wants version %d." \ % (version, DB_VERSION)) print("Please, run the %s/update/update.py script to migrate your database prior to running Yokadi" % \ sharePath) print("See %s/doc/update.md for details" % sharePath) sys.exit(1)
def do_a_remove(self, line): """Remove an alias""" if line in self.aliases: session = db.getSession() del self.aliases[line] aliases = session.query(db.Config).filter_by(name="ALIASES").one() aliases.value = str(repr(self.aliases)) session.add(aliases) session.commit() else: tui.error("No alias with that name. Use a_list to display all aliases")
def onecmd(self, line): """This method is subclassed just to be able to encapsulate it with a try/except bloc""" try: # Decode user input line = line.decode(tui.ENCODING) return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError, e: tui.error("Unicode decoding error. Please check you locale and terminal settings (%s)." % e)
def processDbPathArg(dbPath, dataDir): if not dbPath: return basepaths.getDbPath(dataDir) dbPath = os.path.abspath(dbPath) dbDir = os.path.dirname(dbPath) tui.warning( '--db option is deprecated and will be removed in the next version, use --datadir instead' ) if not os.path.isdir(dbDir): tui.error("Directory '{}' does not exist".format(dbDir)) sys.exit(1) return dbPath
def onecmd(self, line): """This method is subclassed just to be able to encapsulate it with a try/except bloc""" try: # Decode user input line = line.decode(tui.ENCODING) return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError, e: tui.error( "Unicode decoding error. Please check you locale and terminal settings (%s)." % e)
def do_k_edit(self, line): """Edit a keyword k_edit @<keyword>""" session = db.getSession() keyword = dbutils.getKeywordFromName(line) oldName = keyword.name newName = tui.editLine(oldName) if newName == "": print("Cancelled") return lst = session.query(Keyword).filter_by(name=newName).all() if len(lst) == 0: # Simple case: newName does not exist, just rename the existing keyword keyword.name = newName session.merge(keyword) session.commit() print("Keyword %s has been renamed to %s" % (oldName, newName)) return # We already have a keyword with this name, we need to merge print("Keyword %s already exists" % newName) if not tui.confirm("Do you want to merge %s and %s" % (oldName, newName)): return # Check we can merge conflictingTasks = [] for task in keyword.tasks: kwDict = task.getKeywordDict() if oldName in kwDict and newName in kwDict and kwDict[oldName] != kwDict[newName]: conflictingTasks.append(task) if len(conflictingTasks) > 0: # We cannot merge tui.error("Cannot merge keywords %s and %s because they are both" " used with different values in these tasks:" % (oldName, newName)) for task in conflictingTasks: print("- %d, %s" % (task.id, task.title)) print("Edit these tasks and try again") return # Merge for task in keyword.tasks: kwDict = task.getKeywordDict() if newName not in kwDict: kwDict[newName] = kwDict[oldName] del kwDict[oldName] task.setKeywordDict(kwDict) session.delete(keyword) session.commit() print("Keyword %s has been merged with %s" % (oldName, newName))
def do_c_set(self, line): """Set a configuration key to value : c_set <key> <value>""" line = line.split() if len(line) < 2: raise BadUsageException("You should provide two arguments : the parameter key and the value") name = line[0] value = " ".join(line[1:]) p = Config.select(AND(Config.q.name == name, Config.q.system == False)) if p.count() == 0: tui.error("Sorry, no parameter match") else: if self.checkParameterValue(name, value): p[0].value = value tui.info("Parameter updated") else: tui.error("Parameter value is incorrect")
def connectDatabase(dbFileName, createIfNeeded=True, memoryDatabase=False): """Connect to database and create it if needed @param dbFileName: path to database file @type dbFileName: str @param createIfNeeded: Indicate if database must be created if it does not exists (default True) @type createIfNeeded: bool @param memoryDatabase: create db in memory. Only usefull for unit test. Default is false. @type memoryDatabase: bool """ dbFileName = os.path.abspath(dbFileName) if sys.platform == 'win32': connectionString = 'sqlite:/' + dbFileName[0] + '|' + dbFileName[2:] else: connectionString = 'sqlite:' + dbFileName if memoryDatabase: connectionString = "sqlite:/:memory:" connection = connectionForURI(connectionString) sqlhub.processConnection = connection if not os.path.exists(dbFileName) or memoryDatabase: if createIfNeeded: print "Creating database" createTables() # Set database version according to current yokadi release Config(name=DB_VERSION_KEY, value=str(DB_VERSION), system=True, desc="Database schema release number") else: print "Database file (%s) does not exist or is not readable. Exiting" % dbFileName sys.exit(1) # Check version version = getVersion() if version != DB_VERSION: sharePath = os.path.abspath(utils.shareDirPath()) tui.error("Your database version is %d but Yokadi wants version %d." \ % (version, DB_VERSION)) print "Please, run the %s/update/update.py script to migrate your database prior to running Yokadi" % \ sharePath print "See %s/update/README.markdown for details" % sharePath sys.exit(1)
def onecmd(self, line): """This method is subclassed just to be able to encapsulate it with a try/except bloc""" try: # Decode user input line = line return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError as e: tui.error( "Unicode decoding error. Please check you locale and terminal settings (%s)." % e) except UnicodeEncodeError as e: tui.error( "Unicode encoding error. Please check you locale and terminal settings (%s)." % e) except BadUsageException as e: tui.error("*** Bad usage ***\n\t%s" % e) cmd = line.split(' ')[0] self.do_help(cmd) except YokadiException as e: tui.error("*** Yokadi error ***\n\t%s" % e) except IOError as e: # We can get I/O errors when yokadi is piped onto another shell commands # that breaks. print("*** I/O error ***\n\t%s" % e, file=sys.stderr) except KeyboardInterrupt: print("*** Break ***") except Exception as e: tui.error("Unhandled exception (oups)\n\t%s" % e) print("This is a bug of Yokadi, sorry.") print( "Send the above message by email to Yokadi developers ([email protected]) to help them make" " Yokadi better.") cut = "---------------------8<----------------------------------------------" print(cut) traceback.print_exc() print("--") print("Python: %s" % sys.version.replace("\n", " ")) print("SQL Alchemy: %s" % sqlalchemy.__version__) print("OS: %s (%s)" % os.uname()[0:3:2]) print("Yokadi: %s" % yokadi.__version__) print(cut) print()
def do_c_set(self, line): """Set a configuration key to value : c_set <key> <value>""" line = line.split() if len(line) < 2: raise BadUsageException( "You should provide two arguments : the parameter key and the value" ) name = line[0] value = " ".join(line[1:]) p = Config.select(AND(Config.q.name == name, Config.q.system == False)) if p.count() == 0: tui.error("Sorry, no parameter match") else: if self.checkParameterValue(name, value): p[0].value = value tui.info("Parameter updated") else: tui.error("Parameter value is incorrect")
def parse(self, line): """Parse given line to create a keyword filter""" operators = ("=<", ">=", "!=", "<", ">", "=") if " " in line: tui.error("No space in keyword filter !") return if line.startswith("!"): self.negative = True line = line[1:] if not line.startswith("@"): tui.error("Keyword name must be be prefixed with a @") return line = line[1:] # Squash @ line = line.replace("==", "=") # Tolerate == syntax for operator in operators: if operator in line: self.name, self.value = line.split(operator, 1) self.valueOperator = operator try: self.value = int(self.value) except ValueError: tui.error("Keyword value must be an integer (got %s)" % (self.value, self.name)) return break # Exit operator loop else: # No operator found, only keyword name has been provided self.name, self.value = line, None
def onecmd(self, line): """This method is subclassed just to be able to encapsulate it with a try/except bloc""" try: # Decode user input line = line return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError as e: tui.error("Unicode decoding error. Please check you locale and terminal settings (%s)." % e) except UnicodeEncodeError as e: tui.error("Unicode encoding error. Please check you locale and terminal settings (%s)." % e) except BadUsageException as e: tui.error("*** Bad usage ***\n\t%s" % e) cmd = line.split(' ')[0] self.do_help(cmd) except YokadiException as e: tui.error("*** Yokadi error ***\n\t%s" % e) except IOError as e: # We can get I/O errors when yokadi is piped onto another shell commands # that breaks. print("*** I/O error ***\n\t%s" % e, file=sys.stderr) except KeyboardInterrupt: print("*** Break ***") except Exception as e: tui.error("Unhandled exception (oups)\n\t%s" % e) print("This is a bug of Yokadi, sorry.") print("Send the above message by email to Yokadi developers ([email protected]) to help them make" " Yokadi better.") cut = "---------------------8<----------------------------------------------" print(cut) traceback.print_exc() print("--") print("Python: %s" % sys.version.replace("\n", " ")) print("SQL Alchemy: %s" % sqlalchemy.__version__) print("OS: %s (%s)" % os.uname()[0:3:2]) print("Yokadi: %s" % yokadi.__version__) print(cut) print()
def onecmd(self, line): """This method is subclassed just to be able to encapsulate it with a try/except bloc""" try: # Decode user input line = line.decode(tui.ENCODING) return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError, e: tui.error("Unicode decoding error. Please check you locale and terminal settings (%s)." % e) except UnicodeEncodeError, e: tui.error("Unicode encoding error. Please check you locale and terminal settings (%s)." % e) except BadUsageException, e: tui.error("*** Bad usage ***\n\t%s" % e) cmd = line.split(' ')[0] self.do_help(cmd) except YokadiException, e: tui.error("*** Yokadi error ***\n\t%s" % e) except IOError, e: # We can get I/O errors when yokadi is piped onto another shell commands # that breaks. print >> sys.stderr, "*** I/O error ***\n\t%s" % e except KeyboardInterrupt: print "*** Break ***" except Exception, e: tui.error("Unhandled exception (oups)\n\t%s" % e) print "This is a bug of Yokadi, sorry." print "Send the above message by email to Yokadi developers ([email protected]) to help them make Yokadi better." cut = "---------------------8<----------------------------------------------"
try: # Decode user input line = line.decode(tui.ENCODING) return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError, e: tui.error( "Unicode decoding error. Please check you locale and terminal settings (%s)." % e) except UnicodeEncodeError, e: tui.error( "Unicode encoding error. Please check you locale and terminal settings (%s)." % e) except BadUsageException, e: tui.error("*** Bad usage ***\n\t%s" % e) cmd = line.split(' ')[0] self.do_help(cmd) except YokadiException, e: tui.error("*** Yokadi error ***\n\t%s" % e) except IOError, e: # We can get I/O errors when yokadi is piped onto another shell commands # that breaks. print >> sys.stderr, "*** I/O error ***\n\t%s" % e except KeyboardInterrupt: print "*** Break ***" except Exception, e: tui.error("Unhandled exception (oups)\n\t%s" % e) print "This is a bug of Yokadi, sorry." print "Send the above message by email to Yokadi developers ([email protected]) to help them make Yokadi better." cut = "---------------------8<----------------------------------------------"
class YokadiCmd(TaskCmd, ProjectCmd, KeywordCmd, ConfCmd, AliasCmd, Cmd): def __init__(self): Cmd.__init__(self) TaskCmd.__init__(self) ProjectCmd.__init__(self) KeywordCmd.__init__(self) AliasCmd.__init__(self) ConfCmd.__init__(self) self.prompt = "yokadi> " self.historyPath = os.getenv("YOKADI_HISTORY") if not self.historyPath: if os.name == "posix": self.historyPath = os.path.join(os.path.expandvars("$HOME"), ".yokadi_history") else: # Windows location self.historyPath = os.path.join(os.path.expandvars("$APPDATA"), ".yokadi_history") self.loadHistory() self.cryptoMgr = cryptutils.YokadiCryptoManager( ) # Load shared cryptographic manager def emptyline(self): """Executed when input is empty. Reimplemented to do nothing.""" return def default(self, line): nline = resolveAlias(line, self.aliases) if nline != line: return self.onecmd(nline) elif nline.isdigit(): self.do_t_show(nline) elif nline == "_": self.do_t_show(nline) else: raise YokadiException( "Unknown command. Use 'help' to see all available commands") def completedefault(self, text, line, begidx, endidx): """Default completion command. Try to see if command is an alias and find the appropriate complete function if it exists""" nline = resolveAlias(line, self.aliases) compfunc = getattr(self, 'complete_' + nline.split()[0]) matches = compfunc(text, line, begidx, endidx) return matches def do_EOF(self, line): """Quit.""" print return True # Some standard alias do_quit = do_EOF do_q = do_EOF do_exit = do_EOF def onecmd(self, line): """This method is subclassed just to be able to encapsulate it with a try/except bloc""" try: # Decode user input line = line.decode(tui.ENCODING) return Cmd.onecmd(self, line) except YokadiOptionParserNormalExitException: pass except UnicodeDecodeError, e: tui.error( "Unicode decoding error. Please check you locale and terminal settings (%s)." % e) except UnicodeEncodeError, e: tui.error( "Unicode encoding error. Please check you locale and terminal settings (%s)." % e)