Пример #1
0
    def isPassphraseValid(self):
        """Check if user passphrase is valid.
        ie. : if it can decrypt the check crypto word"""
        if not self.passphrase:
            # If no passphrase has been defined, it is definitively not valid !
            return False
        if self.crypto_check:
            try:
                int(self._decrypt(self.crypto_check))
                return True
            except ValueError:
                return False
        else:
            # First time that user enter a passphrase. Store the crypto check
            # for next time usage
            # We use a long string composed of int that we encrypt
            check_word = str(Random().getrandbits(KEY_LENGTH * KEY_LENGTH))
            check_word = adjustString(check_word, 10 * KEY_LENGTH)
            self.crypto_check = self._encrypt(check_word)

            # Save it to database config
            db.getSession().add(
                db.Config(name="CRYPTO_CHECK",
                          value=self.crypto_check,
                          system=True,
                          desc="Cryptographic check data of passphrase"))
            return True
Пример #2
0
    def do_a_edit_command(self, line):
        """Edit the command of an alias.
        a_edit_command <alias name>"""
        session = db.getSession()
        name = line
        if name not in self.aliases:
            raise YokadiException("There is no alias named {}".format(name))

        command = tui.editLine(self.aliases[name])

        session = db.getSession()
        db.Alias.setCommand(session, name, command)
        session.commit()
        self._updateAliasDict()
Пример #3
0
    def do_a_edit_command(self, line):
        """Edit the command of an alias.
        a_edit_command <alias name>"""
        session = db.getSession()
        name = line
        if name not in self.aliases:
            raise YokadiException("There is no alias named {}".format(name))

        command = tui.editLine(self.aliases[name])

        session = db.getSession()
        db.Alias.setCommand(session, name, command)
        session.commit()
        self._updateAliasDict()
Пример #4
0
def eventLoop():
    """Main event loop"""
    delta = timedelta(hours=float(getConfigKey("ALARM_DELAY")))
    suspend = timedelta(hours=float(getConfigKey("ALARM_SUSPEND")))
    cmdDelayTemplate = getConfigKey("ALARM_DELAY_CMD")
    cmdDueTemplate = getConfigKey("ALARM_DUE_CMD")
    session = db.getSession()
    # For the two following dict, task id is key, and value is (duedate, triggerdate)
    triggeredDelayTasks = {}
    triggeredDueTasks = {}
    activeTaskFilter = [
        Task.status != "done", Task.projectId == Project.id,
        Project.active == True
    ]
    while event[0]:
        now = datetime.today().replace(microsecond=0)
        delayTasks = session.query(Task).filter(Task.dueDate < now + delta,
                                                Task.dueDate > now,
                                                *activeTaskFilter)
        dueTasks = session.query(Task).filter(Task.dueDate < now,
                                              *activeTaskFilter)
        processTasks(delayTasks, triggeredDelayTasks, cmdDelayTemplate,
                     suspend)
        processTasks(dueTasks, triggeredDueTasks, cmdDueTemplate, suspend)
        time.sleep(DELAY)
Пример #5
0
    def run(self):
        filename = self.options.filename
        if not filename:
            filename = basepaths.getDbPath()
            print("Using default database (%s)" % filename)

        db.connectDatabase(filename, createIfNeeded=False)
        session = db.getSession()

        # Basic tests :
        if not len(session.query(db.Config).all()) >= 1:
            print(
                "Your database seems broken or not initialised properly. Start yokadi command line tool to do it"
            )
            sys.exit(1)

        # Start ical http handler
        if self.options.icalserver:
            yokadiIcalServer = YokadiIcalServer(self.options.tcpPort,
                                                self.options.tcpListen)
            yokadiIcalServer.start()

        # Start the main event Loop
        try:
            while event[1] != "SIGTERM":
                eventLoop()
                event[0] = True
        except KeyboardInterrupt:
            print("\nExiting...")
Пример #6
0
    def end(self):
        today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        # Adjust idColumn
        maxId = db.getSession().query(func.max(Task.id)).one()[0]
        self.idColumn.width = max(2, len(str(maxId)))

        # Adjust titleColumn
        self.titleColumn.width = self.maxTitleWidth
        totalWidth = sum([x.width for x in self.columns]) + len(self.columns)
        if totalWidth >= self.termWidth:
            self.titleColumn.width -= (totalWidth - self.termWidth) + len(self.columns)
        self.titleColumn.formater = TitleFormater(self.titleColumn.width, self.cryptoMgr)

        # Print table
        for sectionName, taskList in self.taskLists:
            dateSplitters = [(1, "day"), (7, "week"), (30, "month"), (30 * 4, "quarter"), (365, "year")]
            splitterRange, splitterName = dateSplitters.pop()
            splitterText = None
            self._renderTaskListHeader(sectionName)
            for task in taskList:
                while self.splitOnDate and task.creationDate > today - timedelta(splitterRange):
                    splitterText = "Last %s" % splitterName
                    if len(dateSplitters) > 0:
                        splitterRange, splitterName = dateSplitters.pop()
                    else:
                        self.splitOnDate = False

                if splitterText:
                    print(C.GREEN + splitterText.center(totalWidth) + C.RESET, file=self.out)
                    splitterText = None

                self._renderTaskListRow(task)
Пример #7
0
def eventLoop():
    """Main event loop"""
    delta = timedelta(hours=float(getConfigKey("ALARM_DELAY")))
    suspend = timedelta(hours=float(getConfigKey("ALARM_SUSPEND")))
    cmdDelayTemplate = getConfigKey("ALARM_DELAY_CMD")
    cmdDueTemplate = getConfigKey("ALARM_DUE_CMD")
    session = db.getSession()
    # For the two following dict, task id is key, and value is (duedate, triggerdate)
    triggeredDelayTasks = {}
    triggeredDueTasks = {}
    activeTaskFilter = [Task.status != "done",
                        Task.projectId == Project.id,
                        Project.active == True]  # noqa

    def process(now):
        delayTasks = session.query(Task).filter(Task.dueDate < now + delta,
                                                Task.dueDate > now,
                                                *activeTaskFilter)
        dueTasks = session.query(Task).filter(Task.dueDate < now,
                                              *activeTaskFilter)
        processTasks(delayTasks, triggeredDelayTasks, cmdDelayTemplate, suspend)
        processTasks(dueTasks, triggeredDueTasks, cmdDueTemplate, suspend)

    nextProcessTime = datetime.today().replace(microsecond=0)
    while event[0]:
        now = datetime.today().replace(microsecond=0)
        if now > nextProcessTime:
            process(now)
            nextProcessTime = now + timedelta(seconds=PROCESS_INTERVAL)
        time.sleep(EVENTLOOP_INTERVAL)
Пример #8
0
def addTask(projectName, title, keywordDict=None, interactive=True):
    """Adds a task based on title and keywordDict.
    @param projectName: name of project as a string
    @param title: task title as a string
    @param keywordDict: dictionary of keywords (name : value)
    @param interactive: Ask user before creating project (this is the default)
    @type interactive: Bool
    @returns : Task instance on success, None if cancelled."""
    session = db.getSession()
    if keywordDict is None:
        keywordDict = {}

    # Create missing keywords
    if not createMissingKeywords(keywordDict.keys(), interactive=interactive):
        return None

    # Create missing project
    project = getOrCreateProject(projectName, interactive=interactive)
    if not project:
        return None

    # Create task
    task = Task(creationDate=datetime.now().replace(second=0, microsecond=0), project=project, title=title,
                description="", status="new")
    session.add(task)
    task.setKeywordDict(keywordDict)
    session.merge(task)

    return task
Пример #9
0
 def do_p_set_inactive(self, line):
     """Desactivate the given project"""
     session = db.getSession()
     project = getProjectFromName(line)
     project.active = False
     session.merge(project)
     session.commit()
Пример #10
0
def addTask(projectName, title, keywordDict=None, interactive=True):
    """Adds a task based on title and keywordDict.
    @param projectName: name of project as a string
    @param title: task title as a string
    @param keywordDict: dictionary of keywords (name : value)
    @param interactive: Ask user before creating project (this is the default)
    @type interactive: Bool
    @returns : Task instance on success, None if cancelled."""
    session = db.getSession()
    if keywordDict is None:
        keywordDict = {}

    # Create missing keywords
    if not createMissingKeywords(keywordDict.keys(), interactive=interactive):
        return None

    # Create missing project
    project = getOrCreateProject(projectName, interactive=interactive)
    if not project:
        return None

    # Create task
    task = Task(creationDate=datetime.now().replace(second=0, microsecond=0),
                project=project,
                title=title,
                description="",
                status="new")
    session.add(task)
    task.setKeywordDict(keywordDict)
    session.merge(task)

    return task
Пример #11
0
 def _getLock(self):
     """Retrieve the task lock if it exists (else None)"""
     try:
         return db.getSession().query(TaskLock).filter(
             TaskLock.task == self.task).one()
     except NoResultFound:
         return None
Пример #12
0
    def run(self):
        filename = self.options.filename
        if not filename:
            filename = os.path.join(os.path.expandvars("$HOME"), ".yokadi.db")
            print("Using default database (%s)" % filename)

        db.connectDatabase(filename, createIfNeeded=False)
        session = db.getSession()

        # Basic tests :
        if not len(session.query(db.Config).all()) >=1:
            print("Your database seems broken or not initialised properly. Start yokadi command line tool to do it")
            sys.exit(1)

        # Start ical http handler
        if self.options.icalserver:
            yokadiIcalServer = YokadiIcalServer(self.options.tcpPort, self.options.tcpListen)
            yokadiIcalServer.start()

        # Start the main event Loop
        try:
            while event[1] != "SIGTERM":
                eventLoop()
                event[0] = True
        except KeyboardInterrupt:
            print("\nExiting...")
Пример #13
0
    def end(self):
        today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        # Adjust idColumn
        maxId = db.getSession().query(func.max(Task.id)).one()[0]
        self.idColumn.width = max(2, len(str(maxId)))

        # Adjust titleColumn
        self.titleColumn.width = self.maxTitleWidth
        totalWidth = sum([x.width for x in self.columns]) + len(self.columns) - 1
        if totalWidth >= self.termWidth:
            self.titleColumn.width = self.termWidth - (totalWidth - self.titleColumn.width)
        self.titleColumn.formater = TitleFormater(self.titleColumn.width, self.cryptoMgr)

        # Print table
        for sectionName, taskList in self.taskLists:
            dateSplitters = [(1, "day"), (7, "week"), (30, "month"), (30 * 4, "quarter"), (365, "year")]
            splitterRange, splitterName = dateSplitters.pop()
            splitterText = None
            self._renderTaskListHeader(sectionName)
            for task in taskList:
                while self.splitOnDate and task.creationDate > today - timedelta(splitterRange):
                    splitterText = "Last %s" % splitterName
                    if len(dateSplitters) > 0:
                        splitterRange, splitterName = dateSplitters.pop()
                    else:
                        self.splitOnDate = False

                if splitterText:
                    print(C.GREEN + splitterText.center(totalWidth) + C.RESET, file=self.out)
                    splitterText = None

                self._renderTaskListRow(task)
Пример #14
0
    def do_p_edit(self, line):
        """Edit a project.
        p_edit <project name>"""
        session = db.getSession()
        project = dbutils.getOrCreateProject(line, createIfNeeded=False)

        if not project:
            raise YokadiException("Project does not exist.")

        # Create project line
        projectLine = parseutils.createLine(project.name, "", project.getKeywordDict())

        # Edit
        line = tui.editLine(projectLine)

        # Update project
        projectName, garbage, keywordDict = parseutils.parseLine(line)
        if garbage:
            raise BadUsageException("Cannot parse line, got garbage (%s)" % garbage)
        if not dbutils.createMissingKeywords(list(keywordDict.keys())):
            return
        try:
            project.name = projectName
            project.setKeywordDict(keywordDict)
            session.merge(project)
            session.commit()
        except IntegrityError:
            session.rollback()
            raise YokadiException("A project named %s already exists. Please find another name" % projectName)
Пример #15
0
def getItemPropertiesStartingWith(item, field, text):
    """Return a list of item.field starting with text
    @param item: the object item, example : Task, Project, Keyword...
    @param field: the item's field lookup : Project.q.name, Task.q.title, Keyword.q.name. Don't forget the magic q
    @param text: The begining of the text as a str
    @return: list of matching strings"""
    session = db.getSession()
    return [x.name for x in session.query(item).filter(field.like(str(text) + "%"))]
Пример #16
0
 def do_k_list(self, line):
     """List all keywords."""
     for name, taskIds in _listKeywords(db.getSession()):
         if taskIds:
             tasks = ", ".join([str(x) for x in taskIds])
         else:
             tasks = "none"
         print("{} (tasks: {})".format(name, tasks))
Пример #17
0
def createEntriesForProject(project):
    session = db.getSession()
    lst = session.query(Task).filter(Task.projectId == project.id,
                                     Task.status != 'done')

    lst = KeywordFilter(NOTE_KEYWORD, negative=True).apply(lst)
    lst = lst.order_by(desc(Task.urgency))
    return [createEntryForTask(x) for x in lst]
Пример #18
0
def getItemPropertiesStartingWith(item, field, text):
    """Return a list of item.field starting with text
    @param item: the object item, example : Task, Project, Keyword...
    @param field: the item's field lookup : Project.q.name, Task.q.title, Keyword.q.name. Don't forget the magic q
    @param text: The begining of the text as a str
    @return: list of matching strings"""
    session = db.getSession()
    return [x.name for x in session.query(item).filter(field.like(str(text) + "%"))]
Пример #19
0
def createEntriesForProject(project):
    session = db.getSession()
    lst = session.query(Task).filter(Task.projectId == project.id,
                                     Task.status != 'done')

    lst = KeywordFilter(NOTE_KEYWORD, negative=True).apply(lst)
    lst = lst.order_by(desc(Task.urgency))
    return [createEntryForTask(x) for x in lst]
Пример #20
0
 def do_k_list(self, line):
     """List all keywords."""
     for name, taskIds in _listKeywords(db.getSession()):
         if taskIds:
             tasks = ", ".join([str(x) for x in taskIds])
         else:
             tasks = "none"
         print("{} (tasks: {})".format(name, tasks))
Пример #21
0
    def __init__(self, filterLine=None):
        self.name = ""  # Keyword name
        self.value = ""  # Keyword value
        self.negative = False  # Negative filter
        self.valueOperator = "="  # Operator to compare value
        self.session = db.getSession()

        if filterLine:
            self.parse(filterLine)
Пример #22
0
    def do_a_edit_name(self, line):
        """Edit the name of an alias.
        a_edit_name <alias name>"""
        session = db.getSession()
        name = line
        if not name in self.aliases:
            raise YokadiException("There is no alias named {}".format(name))

        newName = tui.editLine(name)
        newName = parseutils.parseOneWordName(newName)

        if newName in self.aliases:
            raise YokadiException("There is already an alias named {}.".format(newName))

        session = db.getSession()
        db.Alias.rename(session, name, newName)
        session.commit()
        self._updateAliasDict()
Пример #23
0
    def do_a_edit_name(self, line):
        """Edit the name of an alias.
        a_edit_name <alias name>"""
        session = db.getSession()
        name = line
        if name not in self.aliases:
            raise YokadiException("There is no alias named {}".format(name))

        newName = tui.editLine(name)
        newName = parseOneWordName(newName)

        if newName in self.aliases:
            raise YokadiException("There is already an alias named {}.".format(newName))

        session = db.getSession()
        db.Alias.rename(session, name, newName)
        session.commit()
        self._updateAliasDict()
Пример #24
0
 def do_p_list(self, line):
     """List all projects."""
     session = db.getSession()
     for project in session.query(Project).all():
         if project.active:
             active = ""
         else:
             active = "(inactive)"
         print("%s %s %s" % (project.name.ljust(20), str(session.query(Task).filter_by(project=project).count()).rjust(4), active))
Пример #25
0
def taskIdCompleter(cmd, text, line, begidx, endidx):
    # TODO: filter on parameter position
    # TODO: potential performance issue with lots of tasks, find a better way to do it
    session = db.getSession()
    tasks = [x for x in session.query(Task).filter(Task.status != 'done') if str(x.id).startswith(text)]
    print()
    for task in tasks:
        # Move that in a renderer class ?
        print("%s: %s / %s" % (task.id, task.project.name, task.title))
    return [str(x.id) for x in tasks]
Пример #26
0
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
Пример #27
0
 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")
Пример #28
0
def taskIdCompleter(cmd, text, line, begidx, endidx):
    # TODO: filter on parameter position
    # TODO: potential performance issue with lots of tasks, find a better way to do it
    session = db.getSession()
    tasks = [x for x in session.query(Task).filter(Task.status != 'done') if str(x.id).startswith(text)]
    print()
    for task in tasks:
        # Move that in a renderer class ?
        print("%s: %s / %s" % (task.id, task.project.name, task.title))
    return [str(x.id) for x in tasks]
Пример #29
0
 def do_p_list(self, line):
     """List all projects."""
     session = db.getSession()
     for project in session.query(Project).all():
         if project.active:
             active = ""
         else:
             active = "(inactive)"
         taskCount = session.query(Task).filter_by(project=project).count()
         print("{:20} {:>4} {}".format(project.name, taskCount, active))
Пример #30
0
 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")
Пример #31
0
 def do_p_list(self, line):
     """List all projects."""
     session = db.getSession()
     for project in session.query(Project).all():
         if project.active:
             active = ""
         else:
             active = "(inactive)"
         taskCount = session.query(Task).filter_by(project=project).count()
         print("{:20} {:>4} {}".format(project.name, taskCount, active))
Пример #32
0
 def __init__(self):
     self.lastTaskId = None  # Last id created, used
     self.lastProjectName = None  # Last project name used
     self.lastTaskIds = []  # Last list of ids selected with t_list
     self.kFilters = []  # Permanent keyword filters (List of KeywordFilter)
     self.pFilter = ""  # Permanent project filter (name of project)
     self.session = db.getSession()
     for name in bugutils.PROPERTY_NAMES:
         dbutils.getOrCreateKeyword(name, interactive=False)
     dbutils.getOrCreateKeyword(NOTE_KEYWORD, interactive=False)
     self.session.commit()
Пример #33
0
    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))
Пример #34
0
 def __init__(self):
     self.lastTaskId = None  # Last id created, used
     self.lastProjectName = None  # Last project name used
     self.lastTaskIds = []  # Last list of ids selected with t_list
     self.kFilters = []  # Permanent keyword filters (List of KeywordFilter)
     self.pFilter = ""  # Permanent project filter (name of project)
     self.session = db.getSession()
     for name in bugutils.PROPERTY_NAMES:
         dbutils.getOrCreateKeyword(name, interactive=False)
     dbutils.getOrCreateKeyword(NOTE_KEYWORD, interactive=False)
     self.session.commit()
Пример #35
0
 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")
Пример #36
0
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
Пример #37
0
    def do_p_merge(self, line):
        session = db.getSession()
        parser = self.parser_p_merge()
        args = parser.parse_args(line)

        src = getProjectFromName(args.source_project)
        dst = getProjectFromName(args.destination_project)
        if not args.force:
            if not tui.confirm("Merge project '{}' into '{}'".format(src.name, dst.name)):
                return
        dst.merge(session, src)
        print("Project '{}' merged into '{}'".format(src.name, dst.name))
Пример #38
0
 def do_p_remove(self, line):
     session = db.getSession()
     parser = self.parser_p_remove()
     args = parser.parse_args(line)
     project = getProjectFromName(args.project)
     nbTasks = len(project.tasks)
     if not args.force:
         if not tui.confirm("Remove project '%s' and its %d tasks" % (project.name, nbTasks)):
             return
     session.delete(project)
     session.commit()
     print("Project removed")
Пример #39
0
 def do_c_get(self, line):
     parser = self.parser_c_get()
     args = parser.parse_args(line)
     key = args.key
     if not key:
         key = "%"
     session = db.getSession()
     k = session.query(Config).filter(Config.name.like(key)).filter_by(system=args.system).all()
     fields = [(x.name, "%s (%s)" % (x.value, x.desc)) for x in k]
     if fields:
         tui.renderFields(fields)
     else:
         raise YokadiException("Configuration key %s does not exist" % line)
Пример #40
0
 def do_c_get(self, line):
     parser = self.parser_c_get()
     args = parser.parse_args(line)
     key = args.key
     if not key:
         key = "%"
     session = db.getSession()
     k = session.query(Config).filter(Config.name.like(key)).filter_by(system=args.system).all()
     fields = [(x.name, "%s (%s)" % (x.value, x.desc)) for x in k]
     if fields:
         tui.renderFields(fields)
     else:
         raise YokadiException("Configuration key %s does not exist" % line)
Пример #41
0
    def do_p_merge(self, line):
        session = db.getSession()
        parser = self.parser_p_merge()
        args = parser.parse_args(line)

        src = getProjectFromName(args.source_project)
        dst = getProjectFromName(args.destination_project)
        if not args.force:
            if not tui.confirm("Merge project '{}' into '{}'".format(
                    src.name, dst.name)):
                return
        dst.merge(session, src)
        print("Project '{}' merged into '{}'".format(src.name, dst.name))
Пример #42
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            print("The keyword %s is used by the following tasks: %s" % (keyword.name,
                                                                         ", ".join(str(task.id) for task in keyword.tasks)))
            if tui.confirm("Do you really want to remove this keyword"):
                session.delete(keyword)
                session.commit()
                print("Keyword %s has been removed" % keyword.name)
Пример #43
0
    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))
Пример #44
0
def getKeywordFromName(name):
    """Returns a keyword from its name, which may start with "@"
    raises a YokadiException if not found
    @param name: the keyword name
    @return: The keyword"""
    session = db.getSession()
    if not name:
        raise YokadiException("No keyword supplied")
    if name.startswith("@"):
        name = name[1:]
    lst = session.query(Keyword).filter_by(name=name).all()
    if len(lst) == 0:
        raise YokadiException("No keyword named '%s' found" % name)
    return lst[0]
Пример #45
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            taskList = ", ".join(str(task.id) for task in keyword.tasks)
            print("The keyword {} is used by the following tasks: {}".format(keyword.name, taskList))
            if not tui.confirm("Do you really want to remove this keyword"):
                return
        session.delete(keyword)
        session.commit()
        print("Keyword {} has been removed".format(keyword.name))
Пример #46
0
def getKeywordFromName(name):
    """Returns a keyword from its name, which may start with "@"
    raises a YokadiException if not found
    @param name: the keyword name
    @return: The keyword"""
    session = db.getSession()
    if not name:
        raise YokadiException("No keyword supplied")
    if name.startswith("@"):
        name = name[1:]
    lst = session.query(Keyword).filter_by(name=name).all()
    if len(lst) == 0:
        raise YokadiException("No keyword named '%s' found" % name)
    return lst[0]
Пример #47
0
 def do_k_add(self, line):
     """Add a keyword
     k_add @<keyword1> [@<keyword2>...]"""
     session = db.getSession()
     if not line:
         raise BadUsageException("You must provide at least one keyword name")
     for keyword in line.split():
         try:
             session.add(Keyword(name=keyword))
             session.commit()
             print("Keyword %s has been created" % keyword)
         except IntegrityError:
             session.rollback()
             print("Keyword %s already exist" % keyword)
Пример #48
0
def getProjectFromName(name, parameterName="project_name"):
    """
    Helper function which returns a project given its name, or raise a
    YokadiException if it does not exist.
    """
    name = name.strip()
    if len(name) == 0:
        raise BadUsageException("Missing <%s> parameter" % parameterName)

    try:
        session = db.getSession()
        return session.query(Project).filter_by(name=name).one()
    except NoResultFound:
        raise YokadiException("Project '%s' not found. Use p_list to see all projects." % name)
Пример #49
0
    def isPassphraseValid(self):
        """Check if user passphrase is valid.
        ie. : if it can decrypt the check crypto word"""
        if not self.passphrase:
            # If no passphrase has been defined, it is definitively not valid !
            return False
        if self.crypto_check:
            try:
                int(self._decrypt(self.crypto_check))
                return True
            except ValueError:
                return False
        else:
            # First time that user enter a passphrase. Store the crypto check
            # for next time usage
            # We use a long string composed of int that we encrypt
            check_word = str(Random().getrandbits(KEY_LENGTH * KEY_LENGTH))
            check_word = adjustString(check_word, 10 * KEY_LENGTH)
            self.crypto_check = self._encrypt(check_word)

            # Save it to database config
            db.getSession().add(db.Config(name="CRYPTO_CHECK", value=self.crypto_check, system=True,
                      desc="Cryptographic check data of passphrase"))
            return True
Пример #50
0
    def do_k_remove(self, line):
        """Remove a keyword
        k_remove @<keyword>"""
        session = db.getSession()
        keyword = dbutils.getKeywordFromName(line)

        if keyword.tasks:
            taskList = ", ".join(str(task.id) for task in keyword.tasks)
            print("The keyword {} is used by the following tasks: {}".format(
                keyword.name, taskList))
            if not tui.confirm("Do you really want to remove this keyword"):
                return
        session.delete(keyword)
        session.commit()
        print("Keyword {} has been removed".format(keyword.name))
Пример #51
0
    def do_a_add(self, line):
        """Add an alias on a command
        Ex. create an alias 'la' for 't_list -a':
        a_add la t_list -a"""
        tokens = line.split()
        if len(tokens) < 2:
            raise BadUsageException("You should provide an alias name and a command")
        name = tokens[0]
        if name in self.aliases:
            raise YokadiException("There is already an alias named {}.".format(name))
        command = " ".join(tokens[1:])

        session = db.getSession()
        db.Alias.add(session, name, command)
        session.commit()
        self._updateAliasDict()
Пример #52
0
def getOrCreateKeyword(keywordName, interactive=True):
    """Get a keyword by its name. Create it if needed
    @param keywordName: keyword name as a string
    @param interactive: Ask user before creating keyword (this is the default)
    @type interactive: Bool
    @return: Keyword instance or None if user cancel creation"""
    session = db.getSession()
    try:
        return session.query(Keyword).filter_by(name=keywordName).one()
    except (NoResultFound, MultipleResultsFound):
        if interactive and not tui.confirm("Keyword '%s' does not exist, create it" % keywordName):
            return None
        keyword = Keyword(name=keywordName)
        session.add(keyword)
        print("Added keyword '%s'" % keywordName)
        return keyword
Пример #53
0
 def do_p_add(self, line):
     """Add new project.
     p_add <projectName>"""
     if not line:
         print("Missing project name.")
         return
     projectName = parseutils.parseOneWordName(line)
     session = db.getSession()
     try:
         project = Project(name=projectName)
         session.add(project)
         session.commit()
     except IntegrityError:
         session.rollback()
         raise YokadiException("A project named %s already exists. Please find another name" % projectName)
     print("Added project '%s'" % projectName)
Пример #54
0
def getOrCreateKeyword(keywordName, interactive=True):
    """Get a keyword by its name. Create it if needed
    @param keywordName: keyword name as a string
    @param interactive: Ask user before creating keyword (this is the default)
    @type interactive: Bool
    @return: Keyword instance or None if user cancel creation"""
    session = db.getSession()
    try:
        return session.query(Keyword).filter_by(name=keywordName).one()
    except (NoResultFound, MultipleResultsFound):
        if interactive and not tui.confirm(
                "Keyword '%s' does not exist, create it" % keywordName):
            return None
        keyword = Keyword(name=keywordName)
        session.add(keyword)
        print("Added keyword '%s'" % keywordName)
        return keyword