summaryrefslogtreecommitdiff
path: root/alot
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2016-12-13 11:53:47 -0800
committerDylan Baker <dylan@pnwbakers.com>2016-12-13 12:34:15 -0800
commit02431efd92060ea5d1f64bfc700ae9b1e5f4907d (patch)
tree5fc98c8c4011bc84c2c87cec26eafd5f3bfbfefe /alot
parent42504da6791fb12527c708759715b7a79d5a1ddb (diff)
Replace mutable keyword arguments
There are a number of cases of mutable keyword arguments (list and dict in this case). Mutable keyword arguments are rather dangerous, since any mutation of the default value is persistent, which will inevitably lead to bugs. For example, imagine this code: def func(def=[]): def.append('foo') return def >>> func() ['foo'] >>> func() ['foo', 'foo'] This is almost certainly not what was intended. This code generally uses the idiom of setting the default value to None, and then assigning with or `value = value or []` which will replace value with the empty list (or dict) when value is falsey, like None or another empty list.
Diffstat (limited to 'alot')
-rw-r--r--alot/account.py11
-rw-r--r--alot/buffers.py4
-rw-r--r--alot/commands/__init__.py6
-rw-r--r--alot/commands/globals.py18
-rw-r--r--alot/db/envelope.py12
-rw-r--r--alot/db/manager.py4
-rw-r--r--alot/db/utils.py3
-rw-r--r--alot/settings/manager.py3
-rw-r--r--alot/settings/utils.py4
-rw-r--r--alot/ui.py9
10 files changed, 45 insertions, 29 deletions
diff --git a/alot/account.py b/alot/account.py
index 6687f13c..2b122e78 100644
--- a/alot/account.py
+++ b/alot/account.py
@@ -52,10 +52,17 @@ class Account(object):
def __init__(self, address=None, aliases=None, alias_regexp=None,
realname=None, gpg_key=None, signature=None,
signature_filename=None, signature_as_attachment=False,
- sent_box=None, sent_tags=['sent'], draft_box=None,
- draft_tags=['draft'], abook=None, sign_by_default=False,
+ sent_box=None, sent_tags=None, draft_box=None,
+ draft_tags=None, abook=None, sign_by_default=False,
encrypt_by_default=u"none",
**rest):
+ sent_tags = sent_tags or []
+ if 'sent' not in sent_tags:
+ sent_tags.append('sent')
+ draft_tags = draft_tags or []
+ if 'draft' not in draft_tags:
+ draft_tags.append('draft')
+
self.address = address
self.aliases = aliases
self.alias_regexp = alias_regexp
diff --git a/alot/buffers.py b/alot/buffers.py
index 6b5cb9c7..e6f6d42c 100644
--- a/alot/buffers.py
+++ b/alot/buffers.py
@@ -618,10 +618,10 @@ class TagListBuffer(Buffer):
modename = 'taglist'
- def __init__(self, ui, alltags=[], filtfun=None):
+ def __init__(self, ui, alltags=None, filtfun=None):
self.filtfun = filtfun
self.ui = ui
- self.tags = alltags
+ self.tags = alltags or []
self.isinitialized = False
self.rebuild()
Buffer.__init__(self, ui, self.body)
diff --git a/alot/commands/__init__.py b/alot/commands/__init__.py
index 7fa83a07..49a096a1 100644
--- a/alot/commands/__init__.py
+++ b/alot/commands/__init__.py
@@ -112,7 +112,7 @@ class registerCommand(object):
"""
def __init__(self, mode, name, help=None, usage=None,
- forced={}, arguments=[]):
+ forced=None, arguments=None):
"""
:param mode: mode identifier
:type mode: str
@@ -133,8 +133,8 @@ class registerCommand(object):
self.name = name
self.help = help
self.usage = usage
- self.forced = forced
- self.arguments = arguments
+ self.forced = forced or {}
+ self.arguments = arguments or []
def __call__(self, klass):
helpstring = self.help or klass.__doc__
diff --git a/alot/commands/globals.py b/alot/commands/globals.py
index d3dddf61..af9eb7f9 100644
--- a/alot/commands/globals.py
+++ b/alot/commands/globals.py
@@ -647,10 +647,10 @@ class HelpCommand(Command):
class ComposeCommand(Command):
"""compose a new email"""
- def __init__(self, envelope=None, headers={}, template=None,
- sender=u'', subject=u'', to=[], cc=[], bcc=[], attach=None,
- omit_signature=False, spawn=None, rest=[],
- encrypt=False, **kwargs):
+ def __init__(self, envelope=None, headers=None, template=None, sender=u'',
+ subject=u'', to=None, cc=None, bcc=None, attach=None,
+ omit_signature=False, spawn=None, rest=None, encrypt=False,
+ **kwargs):
"""
:param envelope: use existing envelope
:type envelope: :class:`~alot.db.envelope.Envelope`
@@ -688,16 +688,16 @@ class ComposeCommand(Command):
self.envelope = envelope
self.template = template
- self.headers = headers
+ self.headers = headers or {}
self.sender = sender
self.subject = subject
- self.to = to
- self.cc = cc
- self.bcc = bcc
+ self.to = to or []
+ self.cc = cc or []
+ self.bcc = bcc or []
self.attach = attach
self.omit_signature = omit_signature
self.force_spawn = spawn
- self.rest = ' '.join(rest)
+ self.rest = ' '.join(rest or [])
self.encrypt = encrypt
@inlineCallbacks
diff --git a/alot/db/envelope.py b/alot/db/envelope.py
index 40a110ea..b9513b1f 100644
--- a/alot/db/envelope.py
+++ b/alot/db/envelope.py
@@ -48,8 +48,8 @@ class Envelope(object):
"""tags to add after successful sendout"""
def __init__(
- self, template=None, bodytext=None, headers=None, attachments=[],
- sign=False, sign_key=None, encrypt=False, tags=[]):
+ self, template=None, bodytext=None, headers=None, attachments=None,
+ sign=False, sign_key=None, encrypt=False, tags=None):
"""
:param template: if not None, the envelope will be initialised by
:meth:`parsing <parse_template>` this string before
@@ -71,12 +71,12 @@ class Envelope(object):
logging.debug('BODY: %s', self.body)
self.body = bodytext or u''
self.headers = headers or {}
- self.attachments = list(attachments)
+ self.attachments = list(attachments) if attachments is not None else []
self.sign = sign
self.sign_key = sign_key
self.encrypt = encrypt
self.encrypt_keys = {}
- self.tags = tags # tags to add after successful sendout
+ self.tags = tags or [] # tags to add after successful sendout
self.sent_time = None
self.modified_since_sent = False
self.sending = False # semaphore to avoid accidental double sendout
@@ -121,12 +121,12 @@ class Envelope(object):
value = fallback
return value
- def get_all(self, key, fallback=[]):
+ def get_all(self, key, fallback=None):
"""returns all header values for given key"""
if key in self.headers:
value = self.headers[key]
else:
- value = fallback
+ value = fallback or []
return value
def add(self, key, value):
diff --git a/alot/db/manager.py b/alot/db/manager.py
index 3e84a6b1..a1c0b8ed 100644
--- a/alot/db/manager.py
+++ b/alot/db/manager.py
@@ -398,7 +398,7 @@ class DBManager(object):
db = Database(path=self.path, mode=mode)
return db.create_query(querystring)
- def add_message(self, path, tags=[], afterwards=None):
+ def add_message(self, path, tags=None, afterwards=None):
"""
Adds a file to the notmuch index.
@@ -409,6 +409,8 @@ class DBManager(object):
:param afterwards: callback to trigger after adding
:type afterwards: callable or None
"""
+ tags = tags or []
+
if self.ro:
raise DatabaseROError()
if not is_subdir_of(path, self.path):
diff --git a/alot/db/utils.py b/alot/db/utils.py
index 62a7b3cf..5acbb017 100644
--- a/alot/db/utils.py
+++ b/alot/db/utils.py
@@ -71,7 +71,7 @@ def add_signature_headers(mail, sigs, error_msg):
)
-def get_params(mail, failobj=list(), header='content-type', unquote=True):
+def get_params(mail, failobj=None, header='content-type', unquote=True):
'''Get Content-Type parameters as dict.
RFC 2045 specifies that parameter names are case-insensitive, so
@@ -83,6 +83,7 @@ def get_params(mail, failobj=list(), header='content-type', unquote=True):
:param unquote: unquote the values
:returns: a `dict` containing the parameters
'''
+ failobj = failobj or []
return {k.lower(): v for k, v in mail.get_params(failobj, header, unquote)}
diff --git a/alot/settings/manager.py b/alot/settings/manager.py
index 4083825a..9fa396a4 100644
--- a/alot/settings/manager.py
+++ b/alot/settings/manager.py
@@ -415,8 +415,9 @@ class SettingsManager(object):
"""returns addresses of known accounts including all their aliases"""
return self._accountmap.keys()
- def get_addressbooks(self, order=[], append_remaining=True):
+ def get_addressbooks(self, order=None, append_remaining=True):
"""returns list of all defined :class:`AddressBook` objects"""
+ order = order or []
abooks = []
for a in order:
if a:
diff --git a/alot/settings/utils.py b/alot/settings/utils.py
index 2048a36c..3b9f1ecc 100644
--- a/alot/settings/utils.py
+++ b/alot/settings/utils.py
@@ -7,7 +7,7 @@ from urwid import AttrSpec
from .errors import ConfigError
-def read_config(configpath=None, specpath=None, checks={}):
+def read_config(configpath=None, specpath=None, checks=None):
"""
get a (validated) config object for given config file path.
@@ -21,6 +21,8 @@ def read_config(configpath=None, specpath=None, checks={}):
:raises: :class:`~alot.settings.errors.ConfigError`
:rtype: `configobj.ConfigObj`
"""
+ checks = checks or {}
+
try:
config = ConfigObj(infile=configpath, configspec=specpath,
file_error=True, encoding='UTF8')
diff --git a/alot/ui.py b/alot/ui.py
index 105560d6..aa9d89c8 100644
--- a/alot/ui.py
+++ b/alot/ui.py
@@ -241,7 +241,7 @@ class UI(object):
self._unlock_callback = afterwards
self._locked = True
- def prompt(self, prefix, text=u'', completer=None, tab=0, history=[]):
+ def prompt(self, prefix, text=u'', completer=None, tab=0, history=None):
"""
prompt for text input.
This returns a :class:`~twisted.defer.Deferred` that calls back with
@@ -260,6 +260,8 @@ class UI(object):
:type history: list of str
:rtype: :class:`twisted.defer.Deferred`
"""
+ history = history or []
+
d = defer.Deferred() # create return deferred
oldroot = self.mainloop.widget
@@ -442,8 +444,8 @@ class UI(object):
self._notificationbar = None
self.update()
- def choice(self, message, choices={'y': 'yes', 'n': 'no'},
- select=None, cancel=None, msg_position='above'):
+ def choice(self, message, choices=None, select=None, cancel=None,
+ msg_position='above'):
"""
prompt user to make a choice.
@@ -462,6 +464,7 @@ class UI(object):
:type msg_position: str
:rtype: :class:`twisted.defer.Deferred`
"""
+ choices = choices or {'y': 'yes', 'n': 'no'}
assert select in choices.values() + [None]
assert cancel in choices.values() + [None]
assert msg_position in ['left', 'above']