summaryrefslogtreecommitdiff
path: root/alot/settings
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2012-08-05 12:51:47 +0100
committerPatrick Totzke <patricktotzke@gmail.com>2012-08-10 13:03:39 +0100
commita23e6fd04b08a2c9af08f25cd0bdf6c6282a8439 (patch)
treef757c5ec09f8afbdf5c3fbc572b91589ce51b081 /alot/settings
parent14178c4e59850d4340e116ce29764cbd469c33be (diff)
cleanup: move SettingsManager to its own file
Diffstat (limited to 'alot/settings')
-rw-r--r--alot/settings/__init__.py394
-rw-r--r--alot/settings/manager.py394
2 files changed, 395 insertions, 393 deletions
diff --git a/alot/settings/__init__.py b/alot/settings/__init__.py
index a92eaf0e..57c351b7 100644
--- a/alot/settings/__init__.py
+++ b/alot/settings/__init__.py
@@ -1,398 +1,6 @@
# Copyright (C) 2011-2012 Patrick Totzke <patricktotzke@gmail.com>
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
-import imp
-import os
-import re
-import errno
-import mailcap
-import logging
-import shutil
-from configobj import ConfigObj, Section
-
-from alot.account import SendmailAccount
-from alot.addressbooks import MatchSdtoutAddressbook, AbookAddressBook
-from alot.helper import pretty_datetime, string_decode
-
-from errors import ConfigError
-from utils import read_config
-from utils import resolve_att
-from checks import force_list
-from checks import mail_container
-from checks import gpg_key
-from checks import attr_triple
-from checks import align_mode
-from theme import Theme
-
-
-DEFAULTSPATH = os.path.join(os.path.dirname(__file__), '..', 'defaults')
-
-
-class SettingsManager(object):
- """Organizes user settings"""
- def __init__(self, alot_rc=None, notmuch_rc=None, theme=None):
- """
- :param alot_rc: path to alot's config file
- :type alot_rc: str
- :param notmuch_rc: path to notmuch's config file
- :type notmuch_rc: str
- :theme: path to initially used theme file
- :type theme: str
- """
- self.hooks = None
- self._mailcaps = mailcap.getcaps()
-
- theme_path = theme or os.path.join(DEFAULTSPATH, 'default.theme')
- self._theme = Theme(theme_path)
- bindings_path = os.path.join(DEFAULTSPATH, 'default.bindings')
- self._bindings = ConfigObj(bindings_path)
- self._config = ConfigObj()
- self._accounts = None
- self._accountmap = None
- self.read_config(alot_rc)
- self.read_notmuch_config(notmuch_rc)
-
- def read_notmuch_config(self, path):
- """parse notmuch's config file from path"""
- spec = os.path.join(DEFAULTSPATH, 'notmuch.rc.spec')
- self._notmuchconfig = read_config(path, spec)
-
- def read_config(self, path):
- """parse alot's config file from path"""
- spec = os.path.join(DEFAULTSPATH, 'alot.rc.spec')
- newconfig = read_config(path, spec,
- checks={'mail_container': mail_container,
- 'force_list': force_list,
- 'align': align_mode,
- 'attrtriple': attr_triple,
- 'gpg_key_hint': gpg_key})
- self._config.merge(newconfig)
-
- hooks_path = os.path.expanduser(self._config.get('hooksfile'))
- try:
- self.hooks = imp.load_source('hooks', hooks_path)
- except:
- logging.debug('unable to load hooks file:%s' % hooks_path)
- if 'bindings' in newconfig:
- newbindings = newconfig['bindings']
- if isinstance(newbindings, Section):
- self._bindings.merge(newbindings)
- # themes
- themestring = newconfig['theme']
- themes_dir = self._config.get('themes_dir')
- if themes_dir:
- themes_dir = os.path.expanduser(themes_dir)
- else:
- themes_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME',
- os.path.expanduser('~/.config')), 'alot', 'themes')
- logging.debug(themes_dir)
-
- if themestring:
- if not os.path.isdir(themes_dir):
- err_msg = 'cannot find theme %s: themes_dir %s is missing'
- raise ConfigError(err_msg % (themestring, themes_dir))
- else:
- theme_path = os.path.join(themes_dir, themestring)
- try:
- self._theme = Theme(theme_path)
- except ConfigError as e:
- err_msg = 'Theme file %s failed validation:\n'
- raise ConfigError((err_msg % themestring) + e.message)
-
- self._accounts = self._parse_accounts(self._config)
- self._accountmap = self._account_table(self._accounts)
-
- def _parse_accounts(self, config):
- """
- read accounts information from config
-
- :param config: valit alot config
- :type config: `configobj.ConfigObj`
- :returns: list of accounts
- """
- accounts = []
- if 'accounts' in config:
- for acc in config['accounts'].sections:
- accsec = config['accounts'][acc]
- args = dict(config['accounts'][acc])
-
- # create abook for this account
- abook = accsec['abook']
- logging.debug('abook defined: %s' % abook)
- if abook['type'] == 'shellcommand':
- cmd = abook['command']
- regexp = abook['regexp']
- if cmd is not None and regexp is not None:
- args['abook'] = MatchSdtoutAddressbook(cmd,
- match=regexp)
- else:
- msg = 'underspecified abook of type \'shellcommand\':'
- msg += '\ncommand: %s\nregexp:%s' % (cmd, regexp)
- raise ConfigError(msg)
- elif abook['type'] == 'abook':
- contacts_path = abook['abook_contacts_file']
- args['abook'] = AbookAddressBook(contacts_path)
- else:
- del(args['abook'])
-
- cmd = args['sendmail_command']
- del(args['sendmail_command'])
- newacc = SendmailAccount(cmd, **args)
- accounts.append(newacc)
- return accounts
-
- def _account_table(self, accounts):
- """
- creates a lookup table (emailaddress -> account) for a given list of
- accounts
-
- :param accounts: list of accounts
- :type accounts: list of `alot.account.Account`
- :returns: hashtable
- :rvalue: dict (str -> `alot.account.Account`)
- """
- accountmap = {}
- for acc in accounts:
- accountmap[acc.address] = acc
- for alias in acc.aliases:
- accountmap[alias] = acc
- return accountmap
-
- def get(self, key, fallback=None):
- """
- look up global config values from alot's config
-
- :param key: key to look up
- :type key: str
- :param fallback: fallback returned if key is not present
- :type fallback: str
- :returns: config value with type as specified in the spec-file
- """
- value = None
- if key in self._config:
- value = self._config[key]
- if isinstance(value, Section):
- value = None
- if value == None:
- value = fallback
- return value
-
- def set(self, key, value):
- """
- setter for global config values
-
- :param key: config option identifise
- :type key: str
- :param value: option to set
- :type value: depends on the specfile :file:`alot.rc.spec`
- """
- self._config[key] = value
-
- def get_notmuch_setting(self, section, key, fallback=None):
- """
- look up config values from notmuch's config
-
- :param section: key is in
- :type section: str
- :param key: key to look up
- :type key: str
- :param fallback: fallback returned if key is not present
- :type fallback: str
- :returns: config value with type as specified in the spec-file
- """
- value = None
- if section in self._notmuchconfig:
- if key in self._notmuchconfig[section]:
- value = self._notmuchconfig[section][key]
- if value == None:
- value = fallback
- return value
-
- def get_theming_attribute(self, mode, name, part=None):
- """
- looks up theming attribute
-
- :param mode: ui-mode (e.g. `search`,`thread`...)
- :type mode: str
- :param name: identifier of the atttribute
- :type name: str
- :rtype: urwid.AttrSpec
- """
- colours = int(self._config.get('colourmode'))
- return self._theme.get_attribute(colours, mode, name, part)
-
- def get_threadline_theming(self, thread):
- """
- looks up theming info a threadline displaying a given thread. This
- wraps around :meth:`~alot.settings.theme.Theme.get_threadline_theming`,
- filling in the current colour mode.
-
- :param thread: thread to theme
- :type thread: alot.db.thread.Thread
- """
- colours = int(self._config.get('colourmode'))
- return self._theme.get_threadline_theming(thread, colours)
-
- def get_tagstring_representation(self, tag, onebelow_normal=None,
- onebelow_focus=None):
- """
- looks up user's preferred way to represent a given tagstring.
-
- :param tag: tagstring
- :type tag: str
- :param onebelow_normal: attribute that shines through if unfocussed
- :type onebelow_normal: urwid.AttrSpec
- :param onebelow_focus: attribute that shines through if focussed
- :type onebelow_focus: urwid.AttrSpec
-
- If `onebelow_normal` or `onebelow_focus` is given these attributes will
- be used as fallbacks for fg/bg values '' and 'default'.
-
- This returns a dictionary mapping
- :normal: to :class:`urwid.AttrSpec` used if unfocussed
- :focussed: to :class:`urwid.AttrSpec` used if focussed
- :translated: to an alternative string representation
- """
- colourmode = int(self._config.get('colourmode'))
- theme = self._theme
- cfg = self._config
- colours = [1, 16, 256]
-
- def colourpick(triple):
- """ pick attribute from triple (mono,16c,256c) according to current
- colourmode"""
- if triple is None:
- return None
- return triple[colours.index(colourmode)]
-
- # global default attributes for tagstrings.
- # These could contain values '' and 'default' which we interpret as
- # "use the values from the widget below"
- default_normal = theme.get_attribute(colourmode, 'global', 'tag')
- default_focus = theme.get_attribute(colourmode, 'global', 'tag_focus')
-
- # local defaults for tagstring attributes. depend on next lower widget
- fallback_normal = resolve_att(onebelow_normal, default_normal)
- fallback_focus = resolve_att(onebelow_focus, default_focus)
-
- for sec in cfg['tags'].sections:
- if re.match('^' + sec + '$', tag):
- normal = resolve_att(colourpick(cfg['tags'][sec]['normal']),
- fallback_normal)
- focus = resolve_att(colourpick(cfg['tags'][sec]['focus']),
- fallback_focus)
-
- translated = cfg['tags'][sec]['translated']
- if translated is None:
- translated = tag
- translation = cfg['tags'][sec]['translation']
- if translation:
- translated = re.sub(translation[0], translation[1], tag)
- break
- else:
- normal = fallback_normal
- focus = fallback_focus
- translated = tag
-
- return {'normal': normal, 'focussed': focus, 'translated': translated}
-
- def get_hook(self, key):
- """return hook (`callable`) identified by `key`"""
- if self.hooks:
- if key in self.hooks.__dict__:
- return self.hooks.__dict__[key]
- return None
-
- def get_keybinding(self, mode, key):
- """look up keybinding from `MODE-maps` sections
-
- :param mode: mode identifier
- :type mode: str
- :param key: urwid-style key identifier
- :type key: str
- :returns: a command line to be applied upon keypress
- :rtype: str
- """
- cmdline = None
- bindings = self._bindings
- if key in bindings.scalars:
- cmdline = bindings[key]
- if mode in bindings.sections:
- if key in bindings[mode].scalars:
- value = bindings[mode][key]
- if value:
- cmdline = value
- return cmdline
-
- def get_accounts(self):
- """
- returns known accounts
-
- :rtype: list of :class:`Account`
- """
- return self._accounts
-
- def get_account_by_address(self, address):
- """
- returns :class:`Account` for a given email address (str)
-
- :param address: address to look up
- :type address: string
- :rtype: :class:`Account` or None
- """
-
- for myad in self.get_addresses():
- if myad in address:
- return self._accountmap[myad]
- return None
-
- def get_main_addresses(self):
- """returns addresses of known accounts without its aliases"""
- return [a.address for a in self._accounts]
-
- def get_addresses(self):
- """returns addresses of known accounts including all their aliases"""
- return self._accountmap.keys()
-
- def get_addressbooks(self, order=[], append_remaining=True):
- """returns list of all defined :class:`AddressBook` objects"""
- abooks = []
- for a in order:
- if a:
- if a.abook:
- abooks.append(a.abook)
- if append_remaining:
- for a in self._accounts:
- if a.abook and a.abook not in abooks:
- abooks.append(a.abook)
- return abooks
-
- def mailcap_find_match(self, *args, **kwargs):
- """
- Propagates :func:`mailcap.find_match` but caches the mailcap (first
- argument)
- """
- return mailcap.findmatch(self._mailcaps, *args, **kwargs)
-
- def represent_datetime(self, d):
- """
- turns a given datetime obj into a unicode string representation.
- This will:
-
- 1) look if a fixed 'timestamp_format' is given in the config
- 2) check if a 'timestamp_format' hook is defined
- 3) use :func:`~alot.helper.pretty_datetime` as fallback
- """
-
- fixed_format = self.get('timestamp_format')
- if fixed_format:
- rep = string_decode(d.strftime(fixed_format), 'UTF-8')
- else:
- format_hook = self.get_hook('timestamp_format')
- if format_hook:
- rep = string_decode(format_hook(d), 'UTF-8')
- else:
- rep = pretty_datetime(d)
- return rep
+from alot.settings.manager import SettingsManager
settings = SettingsManager()
diff --git a/alot/settings/manager.py b/alot/settings/manager.py
new file mode 100644
index 00000000..c336071c
--- /dev/null
+++ b/alot/settings/manager.py
@@ -0,0 +1,394 @@
+# Copyright (C) 2011-2012 Patrick Totzke <patricktotzke@gmail.com>
+# This file is released under the GNU GPL, version 3 or a later revision.
+# For further details see the COPYING file
+import imp
+import os
+import re
+import mailcap
+import logging
+from configobj import ConfigObj, Section
+
+from alot.account import SendmailAccount
+from alot.addressbooks import MatchSdtoutAddressbook, AbookAddressBook
+from alot.helper import pretty_datetime, string_decode
+
+from errors import ConfigError
+from utils import read_config
+from utils import resolve_att
+from checks import force_list
+from checks import mail_container
+from checks import gpg_key
+from checks import attr_triple
+from checks import align_mode
+from theme import Theme
+
+
+DEFAULTSPATH = os.path.join(os.path.dirname(__file__), '..', 'defaults')
+
+
+class SettingsManager(object):
+ """Organizes user settings"""
+ def __init__(self, alot_rc=None, notmuch_rc=None, theme=None):
+ """
+ :param alot_rc: path to alot's config file
+ :type alot_rc: str
+ :param notmuch_rc: path to notmuch's config file
+ :type notmuch_rc: str
+ :theme: path to initially used theme file
+ :type theme: str
+ """
+ self.hooks = None
+ self._mailcaps = mailcap.getcaps()
+
+ theme_path = theme or os.path.join(DEFAULTSPATH, 'default.theme')
+ self._theme = Theme(theme_path)
+ bindings_path = os.path.join(DEFAULTSPATH, 'default.bindings')
+ self._bindings = ConfigObj(bindings_path)
+ self._config = ConfigObj()
+ self._accounts = None
+ self._accountmap = None
+ self.read_config(alot_rc)
+ self.read_notmuch_config(notmuch_rc)
+
+ def read_notmuch_config(self, path):
+ """parse notmuch's config file from path"""
+ spec = os.path.join(DEFAULTSPATH, 'notmuch.rc.spec')
+ self._notmuchconfig = read_config(path, spec)
+
+ def read_config(self, path):
+ """parse alot's config file from path"""
+ spec = os.path.join(DEFAULTSPATH, 'alot.rc.spec')
+ newconfig = read_config(path, spec,
+ checks={'mail_container': mail_container,
+ 'force_list': force_list,
+ 'align': align_mode,
+ 'attrtriple': attr_triple,
+ 'gpg_key_hint': gpg_key})
+ self._config.merge(newconfig)
+
+ hooks_path = os.path.expanduser(self._config.get('hooksfile'))
+ try:
+ self.hooks = imp.load_source('hooks', hooks_path)
+ except:
+ logging.debug('unable to load hooks file:%s' % hooks_path)
+ if 'bindings' in newconfig:
+ newbindings = newconfig['bindings']
+ if isinstance(newbindings, Section):
+ self._bindings.merge(newbindings)
+ # themes
+ themestring = newconfig['theme']
+ themes_dir = self._config.get('themes_dir')
+ if themes_dir:
+ themes_dir = os.path.expanduser(themes_dir)
+ else:
+ themes_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME',
+ os.path.expanduser('~/.config')), 'alot', 'themes')
+ logging.debug(themes_dir)
+
+ if themestring:
+ if not os.path.isdir(themes_dir):
+ err_msg = 'cannot find theme %s: themes_dir %s is missing'
+ raise ConfigError(err_msg % (themestring, themes_dir))
+ else:
+ theme_path = os.path.join(themes_dir, themestring)
+ try:
+ self._theme = Theme(theme_path)
+ except ConfigError as e:
+ err_msg = 'Theme file %s failed validation:\n'
+ raise ConfigError((err_msg % themestring) + e.message)
+
+ self._accounts = self._parse_accounts(self._config)
+ self._accountmap = self._account_table(self._accounts)
+
+ def _parse_accounts(self, config):
+ """
+ read accounts information from config
+
+ :param config: valit alot config
+ :type config: `configobj.ConfigObj`
+ :returns: list of accounts
+ """
+ accounts = []
+ if 'accounts' in config:
+ for acc in config['accounts'].sections:
+ accsec = config['accounts'][acc]
+ args = dict(config['accounts'][acc])
+
+ # create abook for this account
+ abook = accsec['abook']
+ logging.debug('abook defined: %s' % abook)
+ if abook['type'] == 'shellcommand':
+ cmd = abook['command']
+ regexp = abook['regexp']
+ if cmd is not None and regexp is not None:
+ args['abook'] = MatchSdtoutAddressbook(cmd,
+ match=regexp)
+ else:
+ msg = 'underspecified abook of type \'shellcommand\':'
+ msg += '\ncommand: %s\nregexp:%s' % (cmd, regexp)
+ raise ConfigError(msg)
+ elif abook['type'] == 'abook':
+ contacts_path = abook['abook_contacts_file']
+ args['abook'] = AbookAddressBook(contacts_path)
+ else:
+ del(args['abook'])
+
+ cmd = args['sendmail_command']
+ del(args['sendmail_command'])
+ newacc = SendmailAccount(cmd, **args)
+ accounts.append(newacc)
+ return accounts
+
+ def _account_table(self, accounts):
+ """
+ creates a lookup table (emailaddress -> account) for a given list of
+ accounts
+
+ :param accounts: list of accounts
+ :type accounts: list of `alot.account.Account`
+ :returns: hashtable
+ :rvalue: dict (str -> `alot.account.Account`)
+ """
+ accountmap = {}
+ for acc in accounts:
+ accountmap[acc.address] = acc
+ for alias in acc.aliases:
+ accountmap[alias] = acc
+ return accountmap
+
+ def get(self, key, fallback=None):
+ """
+ look up global config values from alot's config
+
+ :param key: key to look up
+ :type key: str
+ :param fallback: fallback returned if key is not present
+ :type fallback: str
+ :returns: config value with type as specified in the spec-file
+ """
+ value = None
+ if key in self._config:
+ value = self._config[key]
+ if isinstance(value, Section):
+ value = None
+ if value is None:
+ value = fallback
+ return value
+
+ def set(self, key, value):
+ """
+ setter for global config values
+
+ :param key: config option identifise
+ :type key: str
+ :param value: option to set
+ :type value: depends on the specfile :file:`alot.rc.spec`
+ """
+ self._config[key] = value
+
+ def get_notmuch_setting(self, section, key, fallback=None):
+ """
+ look up config values from notmuch's config
+
+ :param section: key is in
+ :type section: str
+ :param key: key to look up
+ :type key: str
+ :param fallback: fallback returned if key is not present
+ :type fallback: str
+ :returns: config value with type as specified in the spec-file
+ """
+ value = None
+ if section in self._notmuchconfig:
+ if key in self._notmuchconfig[section]:
+ value = self._notmuchconfig[section][key]
+ if value is None:
+ value = fallback
+ return value
+
+ def get_theming_attribute(self, mode, name, part=None):
+ """
+ looks up theming attribute
+
+ :param mode: ui-mode (e.g. `search`,`thread`...)
+ :type mode: str
+ :param name: identifier of the atttribute
+ :type name: str
+ :rtype: urwid.AttrSpec
+ """
+ colours = int(self._config.get('colourmode'))
+ return self._theme.get_attribute(colours, mode, name, part)
+
+ def get_threadline_theming(self, thread):
+ """
+ looks up theming info a threadline displaying a given thread. This
+ wraps around :meth:`~alot.settings.theme.Theme.get_threadline_theming`,
+ filling in the current colour mode.
+
+ :param thread: thread to theme
+ :type thread: alot.db.thread.Thread
+ """
+ colours = int(self._config.get('colourmode'))
+ return self._theme.get_threadline_theming(thread, colours)
+
+ def get_tagstring_representation(self, tag, onebelow_normal=None,
+ onebelow_focus=None):
+ """
+ looks up user's preferred way to represent a given tagstring.
+
+ :param tag: tagstring
+ :type tag: str
+ :param onebelow_normal: attribute that shines through if unfocussed
+ :type onebelow_normal: urwid.AttrSpec
+ :param onebelow_focus: attribute that shines through if focussed
+ :type onebelow_focus: urwid.AttrSpec
+
+ If `onebelow_normal` or `onebelow_focus` is given these attributes will
+ be used as fallbacks for fg/bg values '' and 'default'.
+
+ This returns a dictionary mapping
+ :normal: to :class:`urwid.AttrSpec` used if unfocussed
+ :focussed: to :class:`urwid.AttrSpec` used if focussed
+ :translated: to an alternative string representation
+ """
+ colourmode = int(self._config.get('colourmode'))
+ theme = self._theme
+ cfg = self._config
+ colours = [1, 16, 256]
+
+ def colourpick(triple):
+ """ pick attribute from triple (mono,16c,256c) according to current
+ colourmode"""
+ if triple is None:
+ return None
+ return triple[colours.index(colourmode)]
+
+ # global default attributes for tagstrings.
+ # These could contain values '' and 'default' which we interpret as
+ # "use the values from the widget below"
+ default_normal = theme.get_attribute(colourmode, 'global', 'tag')
+ default_focus = theme.get_attribute(colourmode, 'global', 'tag_focus')
+
+ # local defaults for tagstring attributes. depend on next lower widget
+ fallback_normal = resolve_att(onebelow_normal, default_normal)
+ fallback_focus = resolve_att(onebelow_focus, default_focus)
+
+ for sec in cfg['tags'].sections:
+ if re.match('^' + sec + '$', tag):
+ normal = resolve_att(colourpick(cfg['tags'][sec]['normal']),
+ fallback_normal)
+ focus = resolve_att(colourpick(cfg['tags'][sec]['focus']),
+ fallback_focus)
+
+ translated = cfg['tags'][sec]['translated']
+ if translated is None:
+ translated = tag
+ translation = cfg['tags'][sec]['translation']
+ if translation:
+ translated = re.sub(translation[0], translation[1], tag)
+ break
+ else:
+ normal = fallback_normal
+ focus = fallback_focus
+ translated = tag
+
+ return {'normal': normal, 'focussed': focus, 'translated': translated}
+
+ def get_hook(self, key):
+ """return hook (`callable`) identified by `key`"""
+ if self.hooks:
+ if key in self.hooks.__dict__:
+ return self.hooks.__dict__[key]
+ return None
+
+ def get_keybinding(self, mode, key):
+ """look up keybinding from `MODE-maps` sections
+
+ :param mode: mode identifier
+ :type mode: str
+ :param key: urwid-style key identifier
+ :type key: str
+ :returns: a command line to be applied upon keypress
+ :rtype: str
+ """
+ cmdline = None
+ bindings = self._bindings
+ if key in bindings.scalars:
+ cmdline = bindings[key]
+ if mode in bindings.sections:
+ if key in bindings[mode].scalars:
+ value = bindings[mode][key]
+ if value:
+ cmdline = value
+ return cmdline
+
+ def get_accounts(self):
+ """
+ returns known accounts
+
+ :rtype: list of :class:`Account`
+ """
+ return self._accounts
+
+ def get_account_by_address(self, address):
+ """
+ returns :class:`Account` for a given email address (str)
+
+ :param address: address to look up
+ :type address: string
+ :rtype: :class:`Account` or None
+ """
+
+ for myad in self.get_addresses():
+ if myad in address:
+ return self._accountmap[myad]
+ return None
+
+ def get_main_addresses(self):
+ """returns addresses of known accounts without its aliases"""
+ return [a.address for a in self._accounts]
+
+ def get_addresses(self):
+ """returns addresses of known accounts including all their aliases"""
+ return self._accountmap.keys()
+
+ def get_addressbooks(self, order=[], append_remaining=True):
+ """returns list of all defined :class:`AddressBook` objects"""
+ abooks = []
+ for a in order:
+ if a:
+ if a.abook:
+ abooks.append(a.abook)
+ if append_remaining:
+ for a in self._accounts:
+ if a.abook and a.abook not in abooks:
+ abooks.append(a.abook)
+ return abooks
+
+ def mailcap_find_match(self, *args, **kwargs):
+ """
+ Propagates :func:`mailcap.find_match` but caches the mailcap (first
+ argument)
+ """
+ return mailcap.findmatch(self._mailcaps, *args, **kwargs)
+
+ def represent_datetime(self, d):
+ """
+ turns a given datetime obj into a unicode string representation.
+ This will:
+
+ 1) look if a fixed 'timestamp_format' is given in the config
+ 2) check if a 'timestamp_format' hook is defined
+ 3) use :func:`~alot.helper.pretty_datetime` as fallback
+ """
+
+ fixed_format = self.get('timestamp_format')
+ if fixed_format:
+ rep = string_decode(d.strftime(fixed_format), 'UTF-8')
+ else:
+ format_hook = self.get_hook('timestamp_format')
+ if format_hook:
+ rep = string_decode(format_hook(d), 'UTF-8')
+ else:
+ rep = pretty_datetime(d)
+ return rep