Пример #1
0
    def do_t_urgency(self, line):
        """Defines urgency of a task.
        t_urgency <id> <value>"""

        tokens = parseutils.simplifySpaces(line).split(" ")
        if len(tokens) != 2:
            raise BadUsageException("You must provide a taskId and an urgency value")
        task = self.getTaskFromId(tokens[0])
        try:
            # Do not use isdigit(), so that we can set negative urgency. This
            # make it possible to stick tasks to the bottom of the list.
            urgency = int(tokens[1])
        except ValueError:
            raise BadUsageException("Task urgency must be a digit")

        if urgency > 100:
            tui.warning("Max urgency is 100")
            urgency = 100
        elif urgency < -99:
            tui.warning("Min urgency is -99")
            urgency = -99

        task.urgency = urgency
        self.session.merge(task)
        self.session.commit()
Пример #2
0
    def do_t_urgency(self, line):
        """Defines urgency of a task.
        t_urgency <id> <value>"""

        tokens = parseutils.simplifySpaces(line).split(" ")
        if len(tokens) != 2:
            raise BadUsageException(
                "You must provide a taskId and an urgency value")
        task = self.getTaskFromId(tokens[0])
        try:
            # Do not use isdigit(), so that we can set negative urgency. This
            # make it possible to stick tasks to the bottom of the list.
            urgency = int(tokens[1])
        except ValueError:
            raise BadUsageException("Task urgency must be a digit")

        if urgency > 100:
            tui.warning("Max urgency is 100")
            urgency = 100
        elif urgency < -99:
            tui.warning("Min urgency is -99")
            urgency = -99

        task.urgency = urgency
        self.session.merge(task)
        self.session.commit()
Пример #3
0
    def _parseListLine(self, parser, line):
        """
        Parse line with parser, returns a tuple of the form
        (options, projectList, filters)
        """
        args = parser.parse_args(line)
        if len(args.filter) > 0:
            projectName, keywordFilters = parseutils.extractKeywords(u" ".join(
                args.filter))
        else:
            projectName = ""
            keywordFilters = []

        if self.kFilters:
            # Add keyword filter
            keywordFilters.extend(self.kFilters)

        if not projectName:
            if self.pFilter:
                # If a project filter is defined, use it as none was provided
                projectName = self.pFilter
            else:
                # Take all project if none provided
                projectName = "%"

        if projectName.startswith("!"):
            projectName = self._realProjectName(projectName[1:])
            projectList = Project.select(NOT(LIKE(Project.q.name,
                                                  projectName)))
        else:
            projectName = self._realProjectName(projectName)
            projectList = Project.select(LIKE(Project.q.name, projectName))

        if projectList.count() == 0:
            raise YokadiException("Found no project matching '%s'" %
                                  projectName)

        # Check keywords exist
        parseutils.warnIfKeywordDoesNotExist(keywordFilters)

        # Filtering and sorting according to parameters
        filters = []

        # Filter on keywords
        for keywordFilter in keywordFilters:
            filters.append(keywordFilter.filter())

        # Search
        if args.search:
            for word in args.search:
                if word.startswith("@"):
                    tui.warning(
                        "Maybe you want keyword search (without -s option) "
                        "instead of plain text search?")
                filters.append(
                    OR(LIKE(Task.q.title, "%" + word + "%"),
                       LIKE(Task.q.description, "%" + word + "%")))

        return args, projectList, filters
Пример #4
0
 def encrypt(self, data):
     """Encrypt user data.
     @return: encrypted data"""
     if not CRYPT:
         tui.warning("Crypto functions not available")
         return data
     self.askPassphrase()
     return self._encrypt(data)
Пример #5
0
 def encrypt(self, data):
     """Encrypt user data.
     @return: encrypted data"""
     if not CRYPT:
         tui.warning("Crypto functions not available")
         return data
     self.askPassphrase()
     return self._encrypt(data)
Пример #6
0
    def _t_edit(self, line):
        """Code shared by t_edit and bug_edit."""
        def editComplete(text, state):
            """ Specific completer for the edit prompt.
            This subfunction should stay here because it needs to access to cmd members"""
            if state == 0:
                origline = readline.get_line_buffer()
                line = origline.lstrip()
                stripped = len(origline) - len(line)
                begidx = readline.get_begidx() - stripped
                endidx = readline.get_endidx() - stripped
                if begidx > 0:
                    self.completion_matches = projectAndKeywordCompleter(
                        "", text, line, begidx, endidx, shift=1)
                else:
                    self.completion_matches = []
            try:
                return self.completion_matches[state]
            except IndexError:
                return None

        task = self.getTaskFromId(line)

        if self.cryptoMgr.isEncrypted(task.title):
            self.cryptoMgr.force_decrypt = True  # Decryption must be turned on to edit
        title = self.cryptoMgr.decrypt(task.title)

        # Create task line
        taskLine = parseutils.createLine("", title, task.getKeywordDict())

        oldCompleter = readline.get_completer(
        )  # Backup previous completer to restore it in the end
        readline.set_completer(editComplete)  # Switch to specific completer

        while True:
            # Edit
            print "(Press Ctrl+C to cancel)"
            try:
                line = tui.editLine(taskLine)
                if not line.strip():
                    tui.warning("Missing title")
                    continue
            except KeyboardInterrupt:
                print
                print "Cancelled"
                task = None
                break
            foo, title, keywordDict = parseutils.parseLine(task.project.name +
                                                           " " + line)
            if self.cryptoMgr.isEncrypted(task.title):
                title = self.cryptoMgr.encrypt(title)
            if dbutils.updateTask(task, task.project.name, title, keywordDict):
                break

        readline.set_completer(oldCompleter)  # Restore standard completer
        return task
Пример #7
0
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
Пример #8
0
 def writeHistory(self):
     """Writes shell history to disk"""
     try:
         # Open r/w and close file to create one if needed
         historyFile = open(self.historyPath, "w", encoding='utf-8')
         historyFile.close()
         readline.set_history_length(1000)
         readline.write_history_file(self.historyPath)
     except Exception as e:
         tui.warning("Fail to save history to %s. Error was:\n\t%s"
                     % (self.historyPath, e))
Пример #9
0
    def _parseListLine(self, parser, line):
        """
        Parse line with parser, returns a tuple of the form
        (options, projectList, filters)
        """
        args = parser.parse_args(line)
        if len(args.filter) > 0:
            projectName, keywordFilters = parseutils.extractKeywords(" ".join(args.filter))
        else:
            projectName = ""
            keywordFilters = []

        if self.kFilters:
            # Add keyword filter
            keywordFilters.extend(self.kFilters)

        if not projectName:
            if self.pFilter:
                # If a project filter is defined, use it as none was provided
                projectName = self.pFilter
            else:
                # Take all project if none provided
                projectName = "%"

        if projectName.startswith("!"):
            projectName = self._realProjectName(projectName[1:])
            projectList = self.session.query(Project).filter(Project.name.notlike(projectName)).all()
        else:
            projectName = self._realProjectName(projectName)
            projectList = self.session.query(Project).filter(Project.name.like(projectName)).all()

        if len(projectList) == 0:
            raise YokadiException("Found no project matching '%s'" % projectName)

        # Check keywords exist
        parseutils.warnIfKeywordDoesNotExist(keywordFilters)

        # Filtering and sorting according to parameters
        filters = []

        # Filter on keywords
        for keywordFilter in keywordFilters:
            filters.append(keywordFilter.filter())

        # Search
        if args.search:
            for word in args.search:
                if word.startswith("@"):
                    tui.warning("Maybe you want keyword search (without -s option) "
                                "instead of plain text search?")
                filters.append(or_(Task.title.like("%" + word + "%"),
                                   Task.description.like("%" + word + "%")))

        return args, projectList, filters
Пример #10
0
    def _t_edit(self, line):
        """Code shared by t_edit and bug_edit."""
        def editComplete(text, state):
            """ Specific completer for the edit prompt.
            This subfunction should stay here because it needs to access to cmd members"""
            if state == 0:
                origline = readline.get_line_buffer()
                line = origline.lstrip()
                stripped = len(origline) - len(line)
                begidx = readline.get_begidx() - stripped
                endidx = readline.get_endidx() - stripped
                if begidx > 0:
                    self.completion_matches = projectAndKeywordCompleter("", text, line, begidx, endidx, shift=1)
                else:
                    self.completion_matches = []
            try:
                return self.completion_matches[state]
            except IndexError:
                return None

        task = self.getTaskFromId(line)

        if self.cryptoMgr.isEncrypted(task.title):
            self.cryptoMgr.force_decrypt = True  # Decryption must be turned on to edit
        title = self.cryptoMgr.decrypt(task.title)

        # Create task line
        taskLine = parseutils.createLine("", title, task.getKeywordDict())

        oldCompleter = readline.get_completer()  # Backup previous completer to restore it in the end
        readline.set_completer(editComplete)  # Switch to specific completer

        while True:
            # Edit
            print("(Press Ctrl+C to cancel)")
            try:
                line = tui.editLine(taskLine)
                if not line.strip():
                    tui.warning("Missing title")
                    continue
            except KeyboardInterrupt:
                print()
                print("Cancelled")
                task = None
                break
            foo, title, keywordDict = parseutils.parseLine(task.project.name + " " + line)
            if self.cryptoMgr.isEncrypted(task.title):
                title = self.cryptoMgr.encrypt(title)
            if dbutils.updateTask(task, task.project.name, title, keywordDict):
                break

        readline.set_completer(oldCompleter)  # Restore standard completer
        self.session.merge(task)
        return task
Пример #11
0
 def writeHistory(self):
     """Writes shell history to disk"""
     try:
         # Open r/w and close file to create one if needed
         historyFile = file(self.historyPath, "w")
         historyFile.close()
         readline.set_history_length(1000)
         readline.write_history_file(self.historyPath)
     except Exception, e:
         tui.warning("Fail to save history to %s. Error was:\n\t%s" %
                     (self.historyPath, e))
Пример #12
0
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
Пример #13
0
    def _parseListLine(self, parser, line):
        """
        Parse line with parser, returns a tuple of the form
        (options, projectList, filters)
        """
        args = parser.parse_args(line)
        if len(args.filter) > 0:
            projectName, filters = parseutils.extractKeywords(" ".join(
                args.filter))
        else:
            projectName = ""
            filters = []

        if self.kFilters:
            # Add keyword filter
            filters.extend(self.kFilters)

        if not projectName:
            if self.pFilter:
                # If a project filter is defined, use it as none was provided
                projectName = self.pFilter
            else:
                # Take all project if none provided
                projectName = "%"

        if projectName.startswith("!"):
            projectName = self._realProjectName(projectName[1:])
            projectList = self.session.query(Project).filter(
                Project.name.notlike(projectName)).all()
        else:
            projectName = self._realProjectName(projectName)
            projectList = self.session.query(Project).filter(
                Project.name.like(projectName)).all()

        if len(projectList) == 0:
            raise YokadiException("Found no project matching '%s'" %
                                  projectName)

        # Check keywords exist
        parseutils.warnIfKeywordDoesNotExist(filters)

        # Search
        if args.search:
            for word in args.search:
                if word.startswith("@"):
                    tui.warning(
                        "Maybe you want keyword search (without -s option) "
                        "instead of plain text search?")
                condition = or_(Task.title.like("%" + word + "%"),
                                Task.description.like("%" + word + "%"))
                filters.append(DbFilter(condition))

        return args, projectList, filters
Пример #14
0
 def writeHistory(self):
     """Writes shell history to disk"""
     try:
         fileutils.createParentDirs(self.historyPath)
         # Open r/w and close file to create one if needed
         historyFile = open(self.historyPath, "w", encoding='utf-8')
         historyFile.close()
         readline.set_history_length(1000)
         readline.write_history_file(self.historyPath)
     except Exception as e:
         tui.warning("Fail to save history to %s. Error was:\n\t%s" %
                     (self.historyPath, e))
Пример #15
0
    def decrypt(self, data):
        """Decrypt user data.
        @return: decrypted data"""
        if not self.isEncrypted(data):
            # Just return data as is if it's not encrypted
            return data

        if not CRYPT:
            tui.warning("Crypto functions not available")
            return data

        if not self.force_decrypt:
            # No flag to force decryption, just return fixed string to indicate
            # data is encrypted
            return "<... encrypted data...>"

        # Ask passphrase if needed and decrypt data
        self.askPassphrase()
        if self.passphrase:
            data = self._decrypt(data)
        else:
            data = "<...Failed to decrypt data...>"
        return data
Пример #16
0
    def decrypt(self, data):
        """Decrypt user data.
        @return: decrypted data"""
        if not self.isEncrypted(data):
            # Just return data as is if it's not encrypted
            return data

        if not CRYPT:
            tui.warning("Crypto functions not available")
            return data

        if not self.force_decrypt:
            # No flag to force decryption, just return fixed string to indicate
            # data is encrypted
            return "<... encrypted data...>"

        # Ask passphrase if needed and decrypt data
        self.askPassphrase()
        if self.passphrase:
            data = self._decrypt(data)
        else:
            data = "<...Failed to decrypt data...>"
        return data
Пример #17
0
def warnYokadiDbEnvVariable():
    if os.getenv('YOKADI_DB'):
        tui.warning('The YOKADI_DB environment variable is deprecated and will be removed in the next version, use the'
                    ' --datadir command-line option instead')
Пример #18
0
    def _t_edit(self, line, keywordEditor=None):
        """Code shared by t_edit and bug_edit.
        if keywordEditor is not None it will be called after editing the task.
        Returns the modified task if OK, None if cancelled"""
        def editComplete(text, state):
            """ Specific completer for the edit prompt.
            This subfunction should stay here because it needs to access to cmd members"""
            if state == 0:
                origline = readline.get_line_buffer()
                line = origline.lstrip()
                stripped = len(origline) - len(line)
                begidx = readline.get_begidx() - stripped
                endidx = readline.get_endidx() - stripped
                if begidx > 0:
                    self.completion_matches = projectAndKeywordCompleter("", text, line, begidx, endidx, shift=1)
                else:
                    self.completion_matches = []
            try:
                return self.completion_matches[state]
            except IndexError:
                return None

        task = self.getTaskFromId(line)

        # Create task line
        keywordDict = task.getKeywordDict()
        userKeywordDict, keywordDict = dbutils.splitKeywordDict(keywordDict)
        taskLine = parseutils.createLine("", task.title, userKeywordDict)

        oldCompleter = readline.get_completer()  # Backup previous completer to restore it in the end
        readline.set_completer(editComplete)  # Switch to specific completer

        # Edit
        try:
            while True:
                print("(Press Ctrl+C to cancel)")
                try:
                    line = tui.editLine(taskLine)
                    if not line.strip():
                        tui.warning("Missing title")
                        continue
                except KeyboardInterrupt:
                    print()
                    print("Cancelled")
                    return None
                _, title, userKeywordDict = parseutils.parseLine(task.project.name + " " + line)

                if dbutils.createMissingKeywords(userKeywordDict.keys()):
                    # We were able to create missing keywords if there were any,
                    # we can now exit the edit loop
                    break
        finally:
            readline.set_completer(oldCompleter)

        keywordDict.update(userKeywordDict)
        if keywordEditor:
            keywordEditor(keywordDict)

        task.title = title
        task.setKeywordDict(keywordDict)
        return task
Пример #19
0
    def _t_edit(self, line, keywordEditor=None):
        """Code shared by t_edit and bug_edit.
        if keywordEditor is not None it will be called after editing the task.
        Returns the modified task if OK, None if cancelled"""
        def editComplete(text, state):
            """ Specific completer for the edit prompt.
            This subfunction should stay here because it needs to access to cmd members"""
            if state == 0:
                origline = readline.get_line_buffer()
                line = origline.lstrip()
                stripped = len(origline) - len(line)
                begidx = readline.get_begidx() - stripped
                endidx = readline.get_endidx() - stripped
                if begidx > 0:
                    self.completion_matches = projectAndKeywordCompleter(
                        "", text, line, begidx, endidx, shift=1)
                else:
                    self.completion_matches = []
            try:
                return self.completion_matches[state]
            except IndexError:
                return None

        task = self.getTaskFromId(line)

        if self.cryptoMgr.isEncrypted(task.title):
            self.cryptoMgr.force_decrypt = True  # Decryption must be turned on to edit
        title = self.cryptoMgr.decrypt(task.title)

        # Create task line
        keywordDict = task.getKeywordDict()
        userKeywordDict, keywordDict = dbutils.splitKeywordDict(keywordDict)
        taskLine = parseutils.createLine("", title, userKeywordDict)

        oldCompleter = readline.get_completer(
        )  # Backup previous completer to restore it in the end
        readline.set_completer(editComplete)  # Switch to specific completer

        # Edit
        try:
            while True:
                print("(Press Ctrl+C to cancel)")
                try:
                    line = tui.editLine(taskLine)
                    if not line.strip():
                        tui.warning("Missing title")
                        continue
                except KeyboardInterrupt:
                    print()
                    print("Cancelled")
                    return None
                _, title, userKeywordDict = parseutils.parseLine(
                    task.project.name + " " + line)
                if self.cryptoMgr.isEncrypted(task.title):
                    title = self.cryptoMgr.encrypt(title)

                if dbutils.createMissingKeywords(userKeywordDict.keys()):
                    # We were able to create missing keywords if there were any,
                    # we can now exit the edit loop
                    break
        finally:
            readline.set_completer(oldCompleter)

        keywordDict.update(userKeywordDict)
        if keywordEditor:
            keywordEditor(keywordDict)

        task.title = title
        task.setKeywordDict(keywordDict)
        return task
Пример #20
0
def warnYokadiDbEnvVariable():
    if os.getenv('YOKADI_DB'):
        tui.warning(
            'The YOKADI_DB environment variable is deprecated and will be removed in the next version, use the'
            ' --datadir command-line option instead')
Пример #21
0
from yokadi.ycli import tui
from yokadi.core import db
from yokadi.core.yokadiexception import YokadiException

from sqlobject import SQLObjectNotFound

# Prefix used to recognise encrypted message
CRYPTO_PREFIX = "---YOKADI-ENCRYPTED-MESSAGE---"
# AES Key length
KEY_LENGTH = 32

try:
    from Crypto.Cipher import AES as Cypher
    CRYPT = True
except ImportError:
    tui.warning("Python Cryptographic Toolkit module not found. You will not be able to use cryptographic function")
    tui.warning("like encrypting or decrypting task title or description")
    tui.warning("You can find pycrypto here http://www.pycrypto.org")
    CRYPT = False

# TODO: add unit test


class YokadiCryptoManager(object):
    """Manager object for Yokadi cryptographic operation"""
    def __init__(self):
        # Cache encryption passphrase
        self.passphrase = None
        # Force decryption (and ask passphrase) instead of decrypting only when passphrase was
        # previously provided
        self.force_decrypt = False
Пример #22
0
from yokadi.core import db
from yokadi.core.yokadiexception import YokadiException

from sqlobject import SQLObjectNotFound

# Prefix used to recognise encrypted message
CRYPTO_PREFIX = "---YOKADI-ENCRYPTED-MESSAGE---"
# AES Key length
KEY_LENGTH = 32

try:
    from Crypto.Cipher import AES as Cypher
    CRYPT = True
except ImportError:
    tui.warning(
        "Python Cryptographic Toolkit module not found. You will not be able to use cryptographic function"
    )
    tui.warning("like encrypting or decrypting task title or description")
    tui.warning("You can find pycrypto here http://www.pycrypto.org")
    CRYPT = False

# TODO: add unit test


class YokadiCryptoManager(object):
    """Manager object for Yokadi cryptographic operation"""
    def __init__(self):
        # Cache encryption passphrase
        self.passphrase = None
        # Force decryption (and ask passphrase) instead of decrypting only when passphrase was
        # previously provided