diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2016-12-13 11:53:47 -0800 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2016-12-13 12:34:15 -0800 |
commit | 02431efd92060ea5d1f64bfc700ae9b1e5f4907d (patch) | |
tree | 5fc98c8c4011bc84c2c87cec26eafd5f3bfbfefe /alot | |
parent | 42504da6791fb12527c708759715b7a79d5a1ddb (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.py | 11 | ||||
-rw-r--r-- | alot/buffers.py | 4 | ||||
-rw-r--r-- | alot/commands/__init__.py | 6 | ||||
-rw-r--r-- | alot/commands/globals.py | 18 | ||||
-rw-r--r-- | alot/db/envelope.py | 12 | ||||
-rw-r--r-- | alot/db/manager.py | 4 | ||||
-rw-r--r-- | alot/db/utils.py | 3 | ||||
-rw-r--r-- | alot/settings/manager.py | 3 | ||||
-rw-r--r-- | alot/settings/utils.py | 4 | ||||
-rw-r--r-- | alot/ui.py | 9 |
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') @@ -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'] |