示例#1
0
def search():
    db = Database()
    query_string = ''
    sort_order = "newest-first"
    first_search_term = 0
    for (num, arg) in enumerate(sys.argv[1:]):
        if arg.startswith('--sort='):
            sort_order = arg.split("=")[1]
            if not sort_order in ("oldest-first", "newest-first"):
                raise Exception("unknown sort order")
        elif not arg.startswith('--'):
            # save the position of the first sys.argv that is a search term
            first_search_term = num + 1

    if first_search_term:
        # mangle arguments wrapping terms with spaces in quotes
        querystr = quote_query_line(sys.argv[first_search_term:])

    qry = Query(db, querystr)
    if sort_order == "oldest-first":
        qry.set_sort(Query.SORT.OLDEST_FIRST)
    else:
        qry.set_sort(Query.SORT.NEWEST_FIRST)
        threads = qry.search_threads()

    for thread in threads:
        print thread
示例#2
0
def search():
    db = Database()
    query_string = ''
    sort_order = "newest-first"
    first_search_term = 0
    for (num, arg) in enumerate(sys.argv[1:]):
        if arg.startswith('--sort='):
            sort_order=arg.split("=")[1]
            if not sort_order in ("oldest-first", "newest-first"):
                raise Exception("unknown sort order")
        elif not arg.startswith('--'):
            # save the position of the first sys.argv that is a search term
            first_search_term = num + 1

    if first_search_term:
        # mangle arguments wrapping terms with spaces in quotes
        querystr = quote_query_line(sys.argv[first_search_term:])

    qry = Query(db, querystr)
    if sort_order == "oldest-first":
        qry.set_sort(Query.SORT.OLDEST_FIRST)
    else:
        qry.set_sort(Query.SORT.NEWEST_FIRST)
        threads = qry.search_threads()

    for thread in threads:
        print thread
示例#3
0
def update(sessionmaker):
    '''
    Update the notmuch database.

    In order that updates are fast, this is how state is resumed.

    1. Get the date of the most recent email that has been imported.
    2. Get the message identifiers of all emails that have been imported.
    3. Search for emails that are no more than a week older than the
       most recent import. This buffer of a week should deal with issues
       of time zones and unsynchronized clocks.
    4. Process emails ascending chronological order.
    5. Skip an email if the message ID for the email has already been
       processed.
    '''
    if offlineimap_is_running():
        raise EnvironmentError('In case offlineimap runs "notmuch new", you should stop offlineimap while importing data from notmuch.')

    session = sessionmaker()
    most_recent = session.query(func.max(NotmuchMessage.datetime)).scalar()

    sql_query = session.query(NotmuchMessage.message_id)
    past_messages = set(row[0] for row in sql_query.distinct())

    start_date = (most_recent.date() - datetime.timedelta(weeks = 1))
    q = Query(Database(), 'date:%s..' % start_date)
    q.set_sort(Query.SORT.OLDEST_FIRST)
    for m in q.search_messages():
        message_id = m.get_message_id()
        if message_id in past_messages:
            logger.debug('Already imported %s' % message_id)
            continue
        past_messages.add(message_id)

        session.add(message(m))
        session.flush() # for foreign key constraints
        session.add_all(attachments(m))

        session.commit()
        logger.info('Added message "id:%s"' % m.get_message_id())
示例#4
0
def main():
    # Handle command line options
    #------------------------------------
    # No option given, print USAGE and exit
    if len(sys.argv) == 1:
        Notmuch().cmd_usage()
    #------------------------------------
    elif sys.argv[1] == 'setup':
        """Interactively setup notmuch for first use."""
        exit("Not implemented.")
    #-------------------------------------
    elif sys.argv[1] == 'new':
        """Check for new and removed messages."""
        Notmuch().cmd_new()
    #-------------------------------------
    elif sys.argv[1] == 'help':
        """Print the help text"""
        Notmuch().cmd_help(sys.argv[1:])
    #-------------------------------------
    elif sys.argv[1] == 'part':
        part()
    #-------------------------------------
    elif sys.argv[1] == 'search':
        search()
    #-------------------------------------
    elif sys.argv[1] == 'show':
        show()
    #-------------------------------------
    elif sys.argv[1] == 'reply':
        db = Database()
        if len(sys.argv) == 2:
            # no search term. abort
            exit("Error: notmuch reply requires at least one search term.")
        # mangle arguments wrapping terms with spaces in quotes
        querystr = quote_query_line(sys.argv[2:])
        msgs = Query(db, querystr).search_messages()
        print Notmuch().format_reply(msgs)
    #-------------------------------------
    elif sys.argv[1] == 'count':
        if len(sys.argv) == 2:
            # no further search term, count all
            querystr = ''
        else:
            # mangle arguments wrapping terms with spaces in quotes
            querystr = quote_query_line(sys.argv[2:])
        print Database().create_query(querystr).count_messages()
    #-------------------------------------
    elif sys.argv[1] == 'tag':
        # build lists of tags to be added and removed
        add = []
        remove = []
        while not sys.argv[2] == '--' and \
                (sys.argv[2].startswith('+') or sys.argv[2].startswith('-')):
            if sys.argv[2].startswith('+'):
                # append to add list without initial +
                add.append(sys.argv.pop(2)[1:])
            else:
                # append to remove list without initial -
                remove.append(sys.argv.pop(2)[1:])
        # skip eventual '--'
        if sys.argv[2] == '--': sys.argv.pop(2)
        # the rest is search terms
        querystr = quote_query_line(sys.argv[2:])
        db = Database(mode=Database.MODE.READ_WRITE)
        msgs = Query(db, querystr).search_messages()
        for msg in msgs:
            # actually add and remove all tags
            map(msg.add_tag, add)
            map(msg.remove_tag, remove)
    #-------------------------------------
    elif sys.argv[1] == 'search-tags':
        if len(sys.argv) == 2:
            # no further search term
            print "\n".join(Database().get_all_tags())
        else:
            # mangle arguments wrapping terms with spaces in quotes
            querystr = quote_query_line(sys.argv[2:])
            db = Database()
            msgs = Query(db, querystr).search_messages()
            print "\n".join([t for t in msgs.collect_tags()])
    #-------------------------------------
    elif sys.argv[1] == 'dump':
        if len(sys.argv) == 2:
            f = sys.stdout
        else:
            f = open(sys.argv[2], "w")
        db = Database()
        query = Query(db, '')
        query.set_sort(Query.SORT.MESSAGE_ID)
        msgs = query.search_messages()
        for msg in msgs:
            f.write("%s (%s)\n" % (msg.get_message_id(), msg.get_tags()))
    #-------------------------------------
    elif sys.argv[1] == 'restore':
        if len(sys.argv) == 2:
            print("No filename given. Reading dump from stdin.")
            f = sys.stdin
        else:
            f = open(sys.argv[2], "r")

        # split the msg id and the tags
        MSGID_TAGS = re.compile("(\S+)\s\((.*)\)$")
        db = Database(mode=Database.MODE.READ_WRITE)

        #read each line of the dump file
        for line in f:
            msgs = MSGID_TAGS.match(line)
            if not msgs:
                sys.stderr.write("Warning: Ignoring invalid input line: %s" %
                                 line)
                continue
            # split line in components and fetch message
            msg_id = msgs.group(1)
            new_tags = set(msgs.group(2).split())
            msg = db.find_message(msg_id)

            if msg == None:
                sys.stderr.write(
                    "Warning: Cannot apply tags to missing message: %s\n" %
                    msg_id)
                continue

            # do nothing if the old set of tags is the same as the new one
            old_tags = set(msg.get_tags())
            if old_tags == new_tags: continue

            # set the new tags
            msg.freeze()
            # only remove tags if the new ones are not a superset anyway
            if not (new_tags > old_tags): msg.remove_all_tags()
            for tag in new_tags:
                msg.add_tag(tag)
            msg.thaw()
    #-------------------------------------
    else:
        # unknown command
        exit("Error: Unknown command '%s' (see \"notmuch help\")" %
             sys.argv[1])
示例#5
0
def main():
    # Handle command line options
    #------------------------------------
    # No option given, print USAGE and exit
    if len(sys.argv) == 1:
        Notmuch().cmd_usage()
    #------------------------------------
    elif sys.argv[1] == 'setup':
       """Interactively setup notmuch for first use."""
       exit("Not implemented.")
    #-------------------------------------
    elif sys.argv[1] == 'new':
        """Check for new and removed messages."""
        Notmuch().cmd_new()
    #-------------------------------------
    elif sys.argv[1] == 'help':
        """Print the help text"""
        Notmuch().cmd_help(sys.argv[1:])
    #-------------------------------------
    elif sys.argv[1] == 'part':
        part()
    #-------------------------------------
    elif sys.argv[1] == 'search':
        search()
    #-------------------------------------
    elif sys.argv[1] == 'show':
        show()
    #-------------------------------------
    elif sys.argv[1] == 'reply':
        db = Database()
        if len(sys.argv) == 2:
            # no search term. abort
            exit("Error: notmuch reply requires at least one search term.")
        # mangle arguments wrapping terms with spaces in quotes
        querystr = quote_query_line(sys.argv[2:])
        msgs = Query(db, querystr).search_messages()
        print Notmuch().format_reply(msgs)
    #-------------------------------------
    elif sys.argv[1] == 'count':
        if len(sys.argv) == 2:
            # no further search term, count all
            querystr = ''
        else:
            # mangle arguments wrapping terms with spaces in quotes
            querystr = quote_query_line(sys.argv[2:])
	print Database().create_query(querystr).count_messages()
    #-------------------------------------
    elif sys.argv[1] == 'tag':
        # build lists of tags to be added and removed
        add = []
        remove = []
        while not sys.argv[2] == '--' and \
                (sys.argv[2].startswith('+') or sys.argv[2].startswith('-')):
                    if sys.argv[2].startswith('+'):
                        # append to add list without initial +
                        add.append(sys.argv.pop(2)[1:])
                    else:
                        # append to remove list without initial -
                        remove.append(sys.argv.pop(2)[1:])
        # skip eventual '--'
        if sys.argv[2] == '--': sys.argv.pop(2)
        # the rest is search terms
        querystr = quote_query_line(sys.argv[2:])
        db = Database(mode=Database.MODE.READ_WRITE)
        msgs  = Query(db, querystr).search_messages()
        for msg in msgs:
            # actually add and remove all tags
            map(msg.add_tag, add)
            map(msg.remove_tag, remove)
    #-------------------------------------
    elif sys.argv[1] == 'search-tags':
        if len(sys.argv) == 2:
            # no further search term
            print "\n".join(Database().get_all_tags())
        else:
            # mangle arguments wrapping terms with spaces in quotes
            querystr = quote_query_line(sys.argv[2:])
            db = Database()
            msgs  = Query(db, querystr).search_messages()
            print "\n".join([t for t in msgs.collect_tags()])
    #-------------------------------------
    elif sys.argv[1] == 'dump':
        # TODO: implement "dump <filename>"
        if len(sys.argv) == 2:
            f = sys.stdout
        else:
            f = open(sys.argv[2], "w")
        db = Database()
        query = Query(db, '')
        query.set_sort(Query.SORT.MESSAGE_ID)
        msgs = query.search_messages()
        for msg in msgs:
            f.write("%s (%s)\n" % (msg.get_message_id(), msg.get_tags()))
    #-------------------------------------
    elif sys.argv[1] == 'restore':
        if len(sys.argv) == 2:
            print("No filename given. Reading dump from stdin.")
            f = sys.stdin
        else:
            f = open(sys.argv[2], "r")

        # split the msg id and the tags
        MSGID_TAGS = re.compile("(\S+)\s\((.*)\)$")
        db = Database(mode=Database.MODE.READ_WRITE)

        #read each line of the dump file
        for line in f:
            msgs = MSGID_TAGS.match(line)
            if not msgs:
                sys.stderr.write("Warning: Ignoring invalid input line: %s" %
                        line)
                continue
            # split line in components and fetch message
            msg_id = msgs.group(1)
            new_tags = set(msgs.group(2).split())
            msg = db.find_message(msg_id)

            if msg == None:
                sys.stderr.write(
                        "Warning: Cannot apply tags to missing message: %s\n" % msg_id)
                continue

            # do nothing if the old set of tags is the same as the new one
            old_tags = set(msg.get_tags())
            if old_tags == new_tags: continue

            # set the new tags
            msg.freeze()
            # only remove tags if the new ones are not a superset anyway
            if not (new_tags > old_tags): msg.remove_all_tags()
            for tag in new_tags: msg.add_tag(tag)
            msg.thaw()
    #-------------------------------------
    else:
        # unknown command
        exit("Error: Unknown command '%s' (see \"notmuch help\")" % sys.argv[1])