summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alot/buffers.py22
-rw-r--r--alot/commands/__init__.py6
-rw-r--r--alot/commands/bufferlist.py2
-rw-r--r--alot/commands/globals.py96
-rw-r--r--alot/commands/search.py27
-rw-r--r--alot/commands/taglist.py1
-rw-r--r--alot/commands/thread.py18
-rw-r--r--alot/completion.py3
-rw-r--r--alot/db/attachment.py7
-rw-r--r--alot/db/envelope.py5
-rw-r--r--alot/db/errors.py3
-rw-r--r--alot/db/message.py18
-rw-r--r--alot/db/utils.py31
-rw-r--r--alot/helper.py10
-rw-r--r--alot/settings/utils.py4
-rw-r--r--alot/ui.py6
16 files changed, 155 insertions, 104 deletions
diff --git a/alot/buffers.py b/alot/buffers.py
index 770fa912..c40c24e5 100644
--- a/alot/buffers.py
+++ b/alot/buffers.py
@@ -291,7 +291,7 @@ class SearchBuffer(Buffer):
def focus_last(self):
self.consume_pipe()
num_lines = len(self.threadlist.get_lines())
- self.body.set_focus(num_lines-1)
+ self.body.set_focus(num_lines - 1)
class ThreadBuffer(Buffer):
@@ -529,27 +529,23 @@ class ThreadBuffer(Buffer):
def focus_next_matching(self, querystring):
"""focus next matching message in depth first order"""
- self.focus_property(
- lambda x: x._message.matches(querystring),
- self._tree.next_position)
+ self.focus_property(lambda x: x._message.matches(querystring),
+ self._tree.next_position)
def focus_prev_matching(self, querystring):
"""focus previous matching message in depth first order"""
- self.focus_property(
- lambda x: x._message.matches(querystring),
- self._tree.prev_position)
+ self.focus_property(lambda x: x._message.matches(querystring),
+ self._tree.prev_position)
def focus_next_unfolded(self):
"""focus next unfolded message in depth first order"""
- self.focus_property(
- lambda x: not x.is_collapsed(x.root),
- self._tree.next_position)
+ self.focus_property(lambda x: not x.is_collapsed(x.root),
+ self._tree.next_position)
def focus_prev_unfolded(self):
"""focus previous unfolded message in depth first order"""
- self.focus_property(
- lambda x: not x.is_collapsed(x.root),
- self._tree.prev_position)
+ self.focus_property(lambda x: not x.is_collapsed(x.root),
+ self._tree.prev_position)
def expand(self, msgpos):
"""expand message at given position"""
diff --git a/alot/commands/__init__.py b/alot/commands/__init__.py
index 8af721ae..cadb6426 100644
--- a/alot/commands/__init__.py
+++ b/alot/commands/__init__.py
@@ -13,6 +13,7 @@ from alot.helper import split_commandstring
class Command(object):
+
"""base class for commands"""
repeatable = False
@@ -70,11 +71,13 @@ def lookup_parser(cmdname, mode):
class CommandParseError(Exception):
+
"""could not parse commandline string"""
pass
class CommandArgumentParser(argparse.ArgumentParser):
+
"""
:class:`~argparse.ArgumentParser` that raises :class:`CommandParseError`
instead of printing to `sys.stderr`"""
@@ -86,6 +89,7 @@ class CommandArgumentParser(argparse.ArgumentParser):
class registerCommand(object):
+
"""
Decorator used to register a :class:`Command` as
handler for command `name` in `mode` so that it
@@ -166,7 +170,7 @@ def commandfactory(cmdline, mode='global'):
cmdline = re.sub(r'"(.*)"', r'"\\"\1\\""', cmdline)
try:
args = split_commandstring(cmdline)
- except ValueError, e:
+ except ValueError as e:
raise CommandParseError(e.message)
args = map(lambda x: alot.helper.string_decode(x, 'utf-8'), args)
logging.debug('ARGS: %s' % args)
diff --git a/alot/commands/bufferlist.py b/alot/commands/bufferlist.py
index 1738a2db..c638f8a0 100644
--- a/alot/commands/bufferlist.py
+++ b/alot/commands/bufferlist.py
@@ -2,7 +2,7 @@
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
from alot.commands import Command, registerCommand
-import globals
+from . import globals
MODE = 'bufferlist'
diff --git a/alot/commands/globals.py b/alot/commands/globals.py
index 01d9bdfc..4f004fe0 100644
--- a/alot/commands/globals.py
+++ b/alot/commands/globals.py
@@ -35,6 +35,7 @@ MODE = 'global'
@registerCommand(MODE, 'exit')
class ExitCommand(Command):
+
"""shut down cleanly"""
@inlineCallbacks
def apply(self, ui):
@@ -50,10 +51,11 @@ class ExitCommand(Command):
@registerCommand(MODE, 'search', usage='search query', arguments=[
- (['--sort'], {'help':'sort order', 'choices':[
+ (['--sort'], {'help': 'sort order', 'choices': [
'oldest_first', 'newest_first', 'message_id', 'unsorted']}),
- (['query'], {'nargs':argparse.REMAINDER, 'help':'search string'})])
+ (['query'], {'nargs': argparse.REMAINDER, 'help': 'search string'})])
class SearchCommand(Command):
+
"""open a new search buffer"""
repeatable = True
@@ -92,8 +94,9 @@ class SearchCommand(Command):
@registerCommand(MODE, 'prompt', arguments=[
- (['startwith'], {'nargs':'?', 'default':'', 'help':'initial content'})])
+ (['startwith'], {'nargs': '?', 'default': '', 'help': 'initial content'})])
class PromptCommand(Command):
+
"""prompts for commandline and interprets it upon select"""
def __init__(self, startwith='', **kwargs):
"""
@@ -124,6 +127,7 @@ class PromptCommand(Command):
@registerCommand(MODE, 'refresh')
class RefreshCommand(Command):
+
"""refresh the current buffer"""
repeatable = True
@@ -133,16 +137,17 @@ class RefreshCommand(Command):
@registerCommand(MODE, 'shellescape', arguments=[
- (['--spawn'], {'action': BooleanAction, 'default':None,
- 'help':'run in terminal window'}),
- (['--thread'], {'action': BooleanAction, 'default':None,
- 'help':'run in separate thread'}),
- (['--refocus'], {'action': BooleanAction, 'help':'refocus current buffer \
+ (['--spawn'], {'action': BooleanAction, 'default': None,
+ 'help': 'run in terminal window'}),
+ (['--thread'], {'action': BooleanAction, 'default': None,
+ 'help': 'run in separate thread'}),
+ (['--refocus'], {'action': BooleanAction, 'help': 'refocus current buffer \
after command has finished'}),
- (['cmd'], {'help':'command line to execute'})],
+ (['cmd'], {'help': 'command line to execute'})],
forced={'shell': True},
)
class ExternalCommand(Command):
+
"""run external command"""
repeatable = True
@@ -201,7 +206,7 @@ class ExternalCommand(Command):
logging.debug('cmdlist: %s' % self.cmdlist)
callerbuffer = ui.current_buffer
- #set standard input for subcommand
+ # set standard input for subcommand
stdin = None
if self.stdin is not None:
# wrap strings in StrinIO so that they behaves like a file
@@ -239,7 +244,7 @@ class ExternalCommand(Command):
return 'success'
else:
return err.strip()
- except OSError, e:
+ except OSError as e:
return str(e)
if self.in_thread:
@@ -258,11 +263,12 @@ class ExternalCommand(Command):
#@registerCommand(MODE, 'edit', arguments=[
-# (['--nospawn'], {'action': 'store_true', 'help':'spawn '}), #todo
+# (['--nospawn'], {'action': 'store_true', 'help':'spawn '}), #todo
# (['path'], {'help':'file to edit'})]
#]
#)
class EditCommand(ExternalCommand):
+
"""edit a file"""
def __init__(self, path, spawn=None, thread=None, **kwargs):
"""
@@ -309,6 +315,7 @@ class EditCommand(ExternalCommand):
@registerCommand(MODE, 'pyshell')
class PythonShellCommand(Command):
+
"""open an interactive python shell for introspection"""
repeatable = True
@@ -320,6 +327,7 @@ class PythonShellCommand(Command):
@registerCommand(MODE, 'repeat')
class RepeatCommand(Command):
+
"""Repeats the command executed last time"""
def __init__(self, **kwargs):
Command.__init__(self, **kwargs)
@@ -332,8 +340,9 @@ class RepeatCommand(Command):
@registerCommand(MODE, 'call', arguments=[
- (['command'], {'help':'python command string to call'})])
+ (['command'], {'help': 'python command string to call'})])
class CallCommand(Command):
+
""" Executes python code """
repeatable = True
@@ -353,7 +362,7 @@ class CallCommand(Command):
if k not in hooks.__dict__:
hooks.__dict__[k] = v
- exec self.command
+ exec(self.command)
except Exception as e:
logging.exception(e)
msg = 'an error occurred during execution of "%s":\n%s'
@@ -361,11 +370,12 @@ class CallCommand(Command):
@registerCommand(MODE, 'bclose', arguments=[
- (['--redraw'], {'action': BooleanAction, 'help':'redraw current buffer \
+ (['--redraw'], {'action': BooleanAction, 'help': 'redraw current buffer \
after command has finished'}),
(['--force'], {'action': 'store_true',
'help': 'never ask for confirmation'})])
class BufferCloseCommand(Command):
+
"""close a buffer"""
repeatable = True
@@ -410,9 +420,10 @@ class BufferCloseCommand(Command):
@registerCommand(MODE, 'bnext', forced={'offset': +1},
help='focus next buffer')
@registerCommand(MODE, 'buffer', arguments=[
- (['index'], {'type':int, 'help':'buffer index to focus'}), ],
+ (['index'], {'type': int, 'help': 'buffer index to focus'}), ],
help='focus buffer with given index')
class BufferFocusCommand(Command):
+
"""focus a :class:`~alot.buffers.Buffer`"""
repeatable = True
@@ -449,6 +460,7 @@ class BufferFocusCommand(Command):
@registerCommand(MODE, 'bufferlist')
class OpenBufferlistCommand(Command):
+
"""open a list of active buffers"""
def __init__(self, filtfun=None, **kwargs):
"""
@@ -469,6 +481,7 @@ class OpenBufferlistCommand(Command):
@registerCommand(MODE, 'taglist')
class TagListCommand(Command):
+
"""opens taglist buffer"""
def __init__(self, filtfun=None, **kwargs):
"""
@@ -492,6 +505,7 @@ class TagListCommand(Command):
@registerCommand(MODE, 'flush')
class FlushCommand(Command):
+
"""flush write operations or retry until committed"""
repeatable = True
@@ -524,16 +538,18 @@ class FlushCommand(Command):
ui.mainloop.set_alarm_in(timeout, f)
if not ui.db_was_locked:
if not self.silent:
- ui.notify('index locked, will try again in %d secs' % timeout)
+ ui.notify(
+ 'index locked, will try again in %d secs' % timeout)
ui.db_was_locked = True
ui.update()
return
-#TODO: choices
+# TODO: choices
@registerCommand(MODE, 'help', arguments=[
- (['commandname'], {'help':'command or \'bindings\''})])
+ (['commandname'], {'help': 'command or \'bindings\''})])
class HelpCommand(Command):
+
"""
display help for a command. Use \'bindings\' to
display all keybings interpreted in current mode.'
@@ -557,7 +573,7 @@ class HelpCommand(Command):
modemaps = dict(settings._bindings[ui.mode].items())
else:
modemaps = {}
- is_scalar = lambda (k, v): k in settings._bindings.scalars
+ is_scalar = lambda k_v: k_v[0] in settings._bindings.scalars
globalmaps = dict(filter(is_scalar, settings._bindings.items()))
# build table
@@ -608,20 +624,21 @@ class HelpCommand(Command):
@registerCommand(MODE, 'compose', arguments=[
- (['--sender'], {'nargs': '?', 'help':'sender'}),
- (['--template'], {'nargs':'?',
- 'help':'path to a template message file'}),
- (['--subject'], {'nargs':'?', 'help':'subject line'}),
- (['--to'], {'nargs':'+', 'help':'recipients'}),
- (['--cc'], {'nargs':'+', 'help':'copy to'}),
- (['--bcc'], {'nargs':'+', 'help':'blind copy to'}),
- (['--attach'], {'nargs':'+', 'help':'attach files'}),
+ (['--sender'], {'nargs': '?', 'help': 'sender'}),
+ (['--template'], {'nargs': '?',
+ 'help': 'path to a template message file'}),
+ (['--subject'], {'nargs': '?', 'help': 'subject line'}),
+ (['--to'], {'nargs': '+', 'help': 'recipients'}),
+ (['--cc'], {'nargs': '+', 'help': 'copy to'}),
+ (['--bcc'], {'nargs': '+', 'help': 'blind copy to'}),
+ (['--attach'], {'nargs': '+', 'help': 'attach files'}),
(['--omit_signature'], {'action': 'store_true',
- 'help':'do not add signature'}),
- (['--spawn'], {'action': BooleanAction, 'default':None,
- 'help':'spawn editor in new terminal'}),
+ 'help': 'do not add signature'}),
+ (['--spawn'], {'action': BooleanAction, 'default': None,
+ 'help': 'spawn editor in new terminal'}),
])
class ComposeCommand(Command):
+
"""compose a new email"""
def __init__(self, envelope=None, headers={}, template=None,
sender=u'', subject=u'', to=[], cc=[], bcc=[], attach=None,
@@ -672,7 +689,7 @@ class ComposeCommand(Command):
if self.envelope is None:
self.envelope = Envelope()
if self.template is not None:
- #get location of tempsdir, containing msg templates
+ # get location of tempsdir, containing msg templates
tempdir = settings.get('template_dir')
tempdir = os.path.expanduser(tempdir)
if not tempdir:
@@ -694,7 +711,7 @@ class ComposeCommand(Command):
return
try:
self.envelope.parse_template(open(path).read())
- except Exception, e:
+ except Exception as e:
ui.notify(str(e), priority='error')
return
@@ -818,9 +835,11 @@ class ComposeCommand(Command):
@registerCommand(MODE, 'move', help='move focus in current buffer',
arguments=[(['movement'], {
- 'nargs':argparse.REMAINDER,
- 'help':'up, down, [half]page up, [half]page down, first'})])
+ 'nargs': argparse.REMAINDER,
+ 'help': 'up, down, [half]page up, '
+ '[half]page down, first'})])
class MoveCommand(Command):
+
"""move in widget"""
def __init__(self, movement=None, **kwargs):
if movement is None:
@@ -832,9 +851,9 @@ class MoveCommand(Command):
def apply(self, ui):
if self.movement in ['up', 'down', 'page up', 'page down']:
ui.mainloop.process_input([self.movement])
- elif self.movement in [ 'halfpage down', 'halfpage up']:
+ elif self.movement in ['halfpage down', 'halfpage up']:
ui.mainloop.process_input(
- ui.mainloop.screen_size[1]/2 * [self.movement.split()[-1]])
+ ui.mainloop.screen_size[1] / 2 * [self.movement.split()[-1]])
elif self.movement == 'first':
if hasattr(ui.current_buffer, "focus_first"):
ui.current_buffer.focus_first()
@@ -847,6 +866,7 @@ class MoveCommand(Command):
class CommandSequenceCommand(Command):
+
"""Meta-Command that just applies a sequence of given Commands in order"""
def __init__(self, cmdline='', **kwargs):
@@ -864,7 +884,7 @@ class CommandSequenceCommand(Command):
# store cmdline for use with 'repeat' command
if cmd.repeatable:
ui.last_commandline = self.cmdline.lstrip()
- except CommandParseError, e:
+ except CommandParseError as e:
ui.notify(e.message, priority='error')
return
yield ui.apply_command(cmd)
diff --git a/alot/commands/search.py b/alot/commands/search.py
index a8ac188f..b5fac4bc 100644
--- a/alot/commands/search.py
+++ b/alot/commands/search.py
@@ -18,6 +18,7 @@ MODE = 'search'
@registerCommand(MODE, 'select')
class OpenThreadCommand(Command):
+
"""open thread in a new buffer"""
def __init__(self, thread=None, **kwargs):
"""
@@ -40,14 +41,15 @@ class OpenThreadCommand(Command):
@registerCommand(MODE, 'refine', help='refine query', arguments=[
- (['--sort'], {'help':'sort order', 'choices':[
+ (['--sort'], {'help': 'sort order', 'choices': [
'oldest_first', 'newest_first', 'message_id', 'unsorted']}),
- (['query'], {'nargs':argparse.REMAINDER, 'help':'search string'})])
+ (['query'], {'nargs': argparse.REMAINDER, 'help': 'search string'})])
@registerCommand(MODE, 'sort', help='set sort order', arguments=[
- (['sort'], {'help':'sort order', 'choices':[
+ (['sort'], {'help': 'sort order', 'choices': [
'oldest_first', 'newest_first', 'message_id', 'unsorted']}),
])
class RefineCommand(Command):
+
"""refine the querystring of this buffer"""
def __init__(self, query=None, sort=None, **kwargs):
"""
@@ -79,6 +81,7 @@ class RefineCommand(Command):
@registerCommand(MODE, 'refineprompt')
class RefinePromptCommand(Command):
+
"""prompt to change this buffers querystring"""
repeatable = True
@@ -90,6 +93,7 @@ class RefinePromptCommand(Command):
@registerCommand(MODE, 'retagprompt')
class RetagPromptCommand(Command):
+
"""prompt to retag selected threads\' tags"""
def apply(self, ui):
thread = ui.current_buffer.get_selected_thread()
@@ -110,8 +114,8 @@ class RetagPromptCommand(Command):
'default': 'True',
'help': 'postpone a writeout to the index'}),
(['--all'], {'action': 'store_true', 'dest': 'allmessages', 'default':
- False, 'help':'retag all messages in search result'}),
- (['tags'], {'help':'comma separated list of tags'})],
+ False, 'help': 'retag all messages in search result'}),
+ (['tags'], {'help': 'comma separated list of tags'})],
help='add tags to all messages in the thread',
)
@registerCommand(MODE, 'retag', forced={'action': 'set'}, arguments=[
@@ -119,8 +123,8 @@ class RetagPromptCommand(Command):
'default': 'True',
'help': 'postpone a writeout to the index'}),
(['--all'], {'action': 'store_true', 'dest': 'allmessages', 'default':
- False, 'help':'retag all messages in search result'}),
- (['tags'], {'help':'comma separated list of tags'})],
+ False, 'help': 'retag all messages in search result'}),
+ (['tags'], {'help': 'comma separated list of tags'})],
help='set tags of all messages in the thread',
)
@registerCommand(MODE, 'untag', forced={'action': 'remove'}, arguments=[
@@ -128,21 +132,22 @@ class RetagPromptCommand(Command):
'default': 'True',
'help': 'postpone a writeout to the index'}),
(['--all'], {'action': 'store_true', 'dest': 'allmessages', 'default':
- False, 'help':'retag all messages in search result'}),
- (['tags'], {'help':'comma separated list of tags'})],
+ False, 'help': 'retag all messages in search result'}),
+ (['tags'], {'help': 'comma separated list of tags'})],
help='remove tags from all messages in the thread',
)
@registerCommand(MODE, 'toggletags', forced={'action': 'toggle'}, arguments=[
(['--no-flush'], {'action': 'store_false', 'dest': 'flush',
'default': 'True',
'help': 'postpone a writeout to the index'}),
- (['tags'], {'help':'comma separated list of tags'})],
+ (['tags'], {'help': 'comma separated list of tags'})],
help="""flip presence of tags on this thread.
A tag is considered present if at least one message contained in this
thread is tagged with it. In that case this command will remove the tag
from every message in the thread.
""")
class TagCommand(Command):
+
"""manipulate message tags"""
repeatable = True
@@ -234,11 +239,13 @@ class TagCommand(Command):
if self.flush:
ui.apply_command(commands.globals.FlushCommand(callback=refresh))
+
@registerCommand(MODE, 'move', help='move focus in search buffer',
arguments=[(['movement'], {
'nargs': argparse.REMAINDER,
'help': 'last'})])
class MoveFocusCommand(MoveCommand):
+
def apply(self, ui):
logging.debug(self.movement)
if self.movement == 'last':
diff --git a/alot/commands/taglist.py b/alot/commands/taglist.py
index c21a7c6a..6e588435 100644
--- a/alot/commands/taglist.py
+++ b/alot/commands/taglist.py
@@ -9,6 +9,7 @@ MODE = 'taglist'
@registerCommand(MODE, 'select')
class TaglistSelectCommand(Command):
+
"""search for messages with selected tag"""
def apply(self, ui):
tagstring = ui.current_buffer.get_selected_tag()
diff --git a/alot/commands/thread.py b/alot/commands/thread.py
index 71bbdbc9..54e6a408 100644
--- a/alot/commands/thread.py
+++ b/alot/commands/thread.py
@@ -99,6 +99,7 @@ def determine_sender(mail, action='reply'):
(['--spawn'], {'action': BooleanAction, 'default': None,
'help': 'open editor in new window'})])
class ReplyCommand(Command):
+
"""reply to message"""
repeatable = True
@@ -252,6 +253,7 @@ class ReplyCommand(Command):
(['--spawn'], {'action': BooleanAction, 'default': None,
'help': 'open editor in new window'})])
class ForwardCommand(Command):
+
"""forward message"""
repeatable = True
@@ -331,6 +333,7 @@ class ForwardCommand(Command):
@registerCommand(MODE, 'bounce')
class BounceMailCommand(Command):
+
"""directly re-send selected message"""
repeatable = True
@@ -396,6 +399,7 @@ class BounceMailCommand(Command):
(['--spawn'], {'action': BooleanAction, 'default': None,
'help': 'open editor in new window'})])
class EditNewCommand(Command):
+
"""edit message in as new"""
def __init__(self, message=None, spawn=None, **kwargs):
"""
@@ -456,6 +460,7 @@ class EditNewCommand(Command):
],
help='display all headers')
class ChangeDisplaymodeCommand(Command):
+
"""fold or unfold messages"""
repeatable = True
@@ -542,6 +547,7 @@ class ChangeDisplaymodeCommand(Command):
],
)
class PipeCommand(Command):
+
"""pipe message(s) to stdin of a shellcommand"""
repeatable = True
@@ -682,6 +688,7 @@ class PipeCommand(Command):
@registerCommand(MODE, 'remove', arguments=[
(['--all'], {'action': 'store_true', 'help': 'remove whole thread'})])
class RemoveCommand(Command):
+
"""remove message(s) from the index"""
repeatable = True
@@ -735,6 +742,7 @@ class RemoveCommand(Command):
],
)
class PrintCommand(PipeCommand):
+
"""print message(s)"""
repeatable = True
@@ -778,6 +786,7 @@ class PrintCommand(PipeCommand):
(['--all'], {'action': 'store_true', 'help': 'save all attachments'}),
(['path'], {'nargs': '?', 'help': 'path to save to'})])
class SaveAttachmentCommand(Command):
+
"""save attachment(s)"""
def __init__(self, all=False, path=None, **kwargs):
"""
@@ -830,13 +839,14 @@ class SaveAttachmentCommand(Command):
try:
dest = attachment.save(self.path)
ui.notify('saved attachment as: %s' % dest)
- except (IOError, OSError), e:
+ except (IOError, OSError) as e:
ui.notify(str(e), priority='error')
else:
ui.notify('canceled')
class OpenAttachmentCommand(Command):
+
"""displays an attachment according to mailcap"""
def __init__(self, attachment, **kwargs):
"""
@@ -902,8 +912,10 @@ class OpenAttachmentCommand(Command):
@registerCommand(MODE, 'move', help='move focus in current buffer',
arguments=[(['movement'], {
'nargs': argparse.REMAINDER,
- 'help': 'up, down, page up, page down, first, last'})])
+ 'help': 'up, down, page up, '
+ 'page down, first, last'})])
class MoveFocusCommand(MoveCommand):
+
def apply(self, ui):
logging.debug(self.movement)
tbuffer = ui.current_buffer
@@ -934,6 +946,7 @@ class MoveFocusCommand(MoveCommand):
@registerCommand(MODE, 'select')
class ThreadSelectCommand(Command):
+
"""select focussed element. The fired action depends on the focus:
- if message summary, this toggles visibility of the message,
- if attachment line, this opens the attachment"""
@@ -979,6 +992,7 @@ class ThreadSelectCommand(Command):
help='flip presence of tags on message(s)',
)
class TagCommand(Command):
+
"""manipulate message tags"""
repeatable = True
diff --git a/alot/completion.py b/alot/completion.py
index 65329d5b..b10aa7f4 100644
--- a/alot/completion.py
+++ b/alot/completion.py
@@ -463,8 +463,7 @@ class CommandCompleter(Completer):
# re-insert whitespaces and correct position
wso = whitespaceoffset
- res = [(' ' * wso + cmd, p + wso) for cmd, p
- in res]
+ res = [(' ' * wso + cmdstr, p + wso) for cmdstr, p in res]
return res
diff --git a/alot/db/attachment.py b/alot/db/attachment.py
index 2f8b37dc..ad996d2e 100644
--- a/alot/db/attachment.py
+++ b/alot/db/attachment.py
@@ -14,6 +14,7 @@ from alot.db.utils import decode_header
class Attachment(object):
+
"""represents a mail attachment"""
def __init__(self, emailpart):
@@ -25,8 +26,8 @@ class Attachment(object):
def __str__(self):
desc = '%s:%s (%s)' % (self.get_content_type(),
- self.get_filename(),
- helper.humanize_size(self.get_size()))
+ self.get_filename(),
+ helper.humanize_size(self.get_size()))
return string_decode(desc)
def get_filename(self):
@@ -87,5 +88,5 @@ class Attachment(object):
cd = self.part['Content-Disposition']
del part['Content-Disposition']
part['Content-Disposition'] = Header(cd, maxlinelen=78,
- header_name='Content-Disposition')
+ header_name='Content-Disposition')
return part
diff --git a/alot/db/envelope.py b/alot/db/envelope.py
index f6787705..0c0d3150 100644
--- a/alot/db/envelope.py
+++ b/alot/db/envelope.py
@@ -20,11 +20,12 @@ import gpgme
from alot.settings import settings
from alot.errors import GPGProblem, GPGCode
-from attachment import Attachment
-from utils import encode_header
+from .attachment import Attachment
+from .utils import encode_header
class Envelope(object):
+
"""a message that is not yet sent and still editable.
It holds references to unencoded! body text and mail headers among other
things. Envelope implements the python container API for easy access of
diff --git a/alot/db/errors.py b/alot/db/errors.py
index 55eb05ef..668ab34e 100644
--- a/alot/db/errors.py
+++ b/alot/db/errors.py
@@ -8,15 +8,18 @@ class DatabaseError(Exception):
class DatabaseROError(DatabaseError):
+
"""cannot write to read-only database"""
pass
class DatabaseLockedError(DatabaseError):
+
"""cannot write to locked index"""
pass
class NonexistantObjectError(DatabaseError):
+
"""requested thread or message does not exist in the index"""
pass
diff --git a/alot/db/message.py b/alot/db/message.py
index 002f7cf9..4249f8c8 100644
--- a/alot/db/message.py
+++ b/alot/db/message.py
@@ -10,12 +10,13 @@ from notmuch import NullPointerError
import alot.helper as helper
from alot.settings import settings
-from utils import extract_headers, extract_body, message_from_file
+from .utils import extract_headers, extract_body, message_from_file
from alot.db.utils import decode_header
-from attachment import Attachment
+from .attachment import Attachment
class Message(object):
+
"""
a persistent notmuch message object.
It it uses a :class:`~alot.db.DBManager` for cached manipulation
@@ -36,10 +37,10 @@ class Message(object):
self._thread = thread
casts_date = lambda: datetime.fromtimestamp(msg.get_date())
self._datetime = helper.safely_get(casts_date,
- ValueError, None)
+ ValueError, None)
self._filename = msg.get_filename()
author = helper.safely_get(lambda: msg.get_header('From'),
- NullPointerError)
+ NullPointerError)
self._from = decode_header(author)
self._email = None # will be read upon first use
self._attachments = None # will be read upon first use
@@ -102,8 +103,7 @@ class Message(object):
def get_tags(self):
"""returns tags attached to this message as list of strings"""
- l = list(self._tags)
- l.sort()
+ l = sorted(self._tags)
return l
def get_thread(self):
@@ -130,7 +130,7 @@ class Message(object):
:rtype: str
"""
- if self._datetime == None:
+ if self._datetime is None:
res = None
else:
res = settings.represent_datetime(self._datetime)
@@ -235,7 +235,7 @@ class Message(object):
'application/pgp-signature']:
self._attachments.append(Attachment(part))
elif cd.startswith('inline'):
- if filename != None and ct != 'application/pgp':
+ if filename is not None and ct != 'application/pgp':
self._attachments.append(Attachment(part))
return self._attachments
@@ -243,7 +243,7 @@ class Message(object):
"""
returns bodystring extracted from this mail
"""
- #TODO: allow toggle commands to decide which part is considered body
+ # TODO: allow toggle commands to decide which part is considered body
return extract_body(self.get_email())
def get_text_content(self):
diff --git a/alot/db/utils.py b/alot/db/utils.py
index db8de0de..ba6d466e 100644
--- a/alot/db/utils.py
+++ b/alot/db/utils.py
@@ -69,7 +69,7 @@ def get_params(mail, failobj=list(), header='content-type', unquote=True):
:param unquote: unquote the values
:returns: a `dict` containing the parameters
'''
- return {k.lower():v for k, v in mail.get_params(failobj, header, unquote)}
+ return {k.lower(): v for k, v in mail.get_params(failobj, header, unquote)}
def message_from_file(handle):
@@ -80,7 +80,8 @@ def message_from_file(handle):
message are added to the returned message object.
:param handle: a file-like object
- :returns: :class:`email.message.Message` possibly augmented with decrypted data
+ :returns: :class:`email.message.Message` possibly augmented with
+ decrypted data
'''
m = email.message_from_file(handle)
@@ -95,7 +96,7 @@ def message_from_file(handle):
# handle OpenPGP signed data
if (m.is_multipart() and
m.get_content_subtype() == 'signed' and
- p.get('protocol', None) == app_pgp_sig):
+ p.get('protocol', None) == app_pgp_sig):
# RFC 3156 is quite strict:
# * exactly two messages
# * the second is of type 'application/pgp-signature'
@@ -132,7 +133,7 @@ def message_from_file(handle):
elif (m.is_multipart() and
m.get_content_subtype() == 'encrypted' and
p.get('protocol', None) == app_pgp_enc and
- 'Version: 1' in m.get_payload(0).get_payload()):
+ 'Version: 1' in m.get_payload(0).get_payload()):
# RFC 3156 is quite strict:
# * exactly two messages
# * the first is of type 'application/pgp-encrypted'
@@ -143,7 +144,8 @@ def message_from_file(handle):
ct = m.get_payload(0).get_content_type()
if ct != app_pgp_enc:
- malformed = 'expected Content-Type: {0}, got: {1}'.format(app_pgp_enc, ct)
+ malformed = 'expected Content-Type: {0}, got: {1}'.format(
+ app_pgp_enc, ct)
want = 'application/octet-stream'
ct = m.get_payload(1).get_content_type()
@@ -228,7 +230,7 @@ def extract_headers(mail, headers=None):
:type headers: list of str
"""
headertext = u''
- if headers == None:
+ if headers is None:
headers = mail.keys()
for key in headers:
value = u''
@@ -251,12 +253,14 @@ def extract_body(mail, types=None):
:type types: list of str
"""
- preferred = 'text/plain' if settings.get('prefer_plaintext') else 'text/html'
+ preferred = 'text/plain' if settings.get(
+ 'prefer_plaintext') else 'text/html'
has_preferred = False
# see if the mail has our preferred type
- if types == None:
- has_preferred = list(typed_subpart_iterator(mail, *preferred.split('/')))
+ if types is None:
+ has_preferred = list(typed_subpart_iterator(
+ mail, *preferred.split('/')))
body_parts = []
for part in mail.walk():
@@ -279,7 +283,7 @@ def extract_body(mail, types=None):
raw_payload = string_decode(raw_payload, enc)
body_parts.append(string_sanitize(raw_payload))
else:
- #get mime handler
+ # get mime handler
key = 'copiousoutput'
handler, entry = settings.mailcap_find_match(ctype, key=key)
tempfile_name = None
@@ -294,8 +298,8 @@ def extract_body(mail, types=None):
nametemplate = entry.get('nametemplate', '%s')
prefix, suffix = parse_mailcap_nametemplate(nametemplate)
tmpfile = tempfile.NamedTemporaryFile(delete=False,
- prefix=prefix,
- suffix=suffix)
+ prefix=prefix,
+ suffix=suffix)
# write payload to tmpfile
tmpfile.write(raw_payload)
tmpfile.close()
@@ -313,7 +317,8 @@ def extract_body(mail, types=None):
logging.debug('parms: %s' % str(parms))
cmdlist = split_commandstring(cmd)
# call handler
- rendered_payload, errmsg, retval = helper.call_cmd(cmdlist, stdin=stdin)
+ rendered_payload, errmsg, retval = helper.call_cmd(
+ cmdlist, stdin=stdin)
# remove tempfile
if tempfile_name:
diff --git a/alot/helper.py b/alot/helper.py
index c5820b8c..9733b045 100644
--- a/alot/helper.py
+++ b/alot/helper.py
@@ -384,10 +384,10 @@ def guess_mimetype(blob):
#
# the version with open() is the bindings shipped with the file source from
# http://darwinsys.com/file/ - this is what is used by the python-magic
- # package on Debian/Ubuntu. However it is not available on pypi/via pip.
+ # package on Debian/Ubuntu. However, it is not available on pypi/via pip.
#
- # the version with from_buffer() is from https://github.com/ahupp/python-magic
- # which is installable via pip.
+ # the version with from_buffer() is available at
+ # https://github.com/ahupp/python-magic and directly installable via pip.
#
# for more detail see https://github.com/pazz/alot/pull/588
if hasattr(magic, 'open'):
@@ -421,8 +421,8 @@ def guess_encoding(blob):
# http://darwinsys.com/file/ - this is what is used by the python-magic
# package on Debian/Ubuntu. However it is not available on pypi/via pip.
#
- # the version with from_buffer() is from https://github.com/ahupp/python-magic
- # which is installable via pip.
+ # the version with from_buffer() is available at
+ # https://github.com/ahupp/python-magic and directly installable via pip.
#
# for more detail see https://github.com/pazz/alot/pull/588
if hasattr(magic, 'open'):
diff --git a/alot/settings/utils.py b/alot/settings/utils.py
index c3dbf3b0..f4cfecbc 100644
--- a/alot/settings/utils.py
+++ b/alot/settings/utils.py
@@ -41,11 +41,11 @@ def read_config(configpath=None, specpath=None, checks={}):
except ConfigObjError as e:
raise ConfigError(e.message)
- if results != True:
+ if results is not True:
error_msg = ''
for (section_list, key, res) in flatten_errors(config, results):
if key is not None:
- if res == False:
+ if res is False:
msg = 'key "%s" in section "%s" is missing.'
msg = msg % (key, ', '.join(section_list))
else:
diff --git a/alot/ui.py b/alot/ui.py
index c7dbb269..6c84c161 100644
--- a/alot/ui.py
+++ b/alot/ui.py
@@ -7,7 +7,6 @@ from twisted.internet import reactor, defer
from settings import settings
from buffers import BufferlistBuffer
-from commands import commandfactory
from alot.commands import CommandParseError
from alot.commands.globals import CommandSequenceCommand
from alot.helper import string_decode
@@ -127,7 +126,7 @@ class UI(object):
self.notify(e.message, priority='error')
# move keys are always passed
elif cmdline in ['move up', 'move down', 'move page up',
- 'move page down']:
+ 'move page down']:
return [cmdline[5:]]
key = keys[0]
@@ -165,7 +164,8 @@ class UI(object):
def apply_commandline(self, cmdline):
"""
Dispatches the interpretation of the command line string to
- :class:`CommandSequenceCommand <alot.commands.globals.CommandSequenceCommand>`.
+ :class:`CommandSequenceCommand
+ <alot.commands.globals.CommandSequenceCommand>`.
:param cmdline: command line to interpret
:type cmdline: str