From 6cc3e22eaa6a16e597c051484844d7f13102e4f7 Mon Sep 17 00:00:00 2001 From: Patrick Totzke Date: Sun, 11 Mar 2012 14:40:34 +0000 Subject: group settings into a submodule --- alot/account.py | 4 +- alot/checks.py | 21 --- alot/errors.py | 4 - alot/helper.py | 39 +---- alot/settings.py | 398 ---------------------------------------------- alot/settings/__init__.py | 398 ++++++++++++++++++++++++++++++++++++++++++++++ alot/settings/checks.py | 21 +++ alot/settings/errors.py | 4 + 8 files changed, 426 insertions(+), 463 deletions(-) delete mode 100644 alot/checks.py delete mode 100644 alot/errors.py delete mode 100644 alot/settings.py create mode 100644 alot/settings/__init__.py create mode 100644 alot/settings/checks.py create mode 100644 alot/settings/errors.py (limited to 'alot') diff --git a/alot/account.py b/alot/account.py index 0e590953..8faee595 100644 --- a/alot/account.py +++ b/alot/account.py @@ -7,7 +7,7 @@ import os import glob import shlex -import helper +from alot.settings.utils import read_config class SendingMailFailed(RuntimeError): @@ -201,7 +201,7 @@ class AbookAddressBook(AddressBook): DEFAULTSPATH = os.path.join(os.path.dirname(__file__), 'defaults') self._spec = os.path.join(DEFAULTSPATH, 'abook_contacts.spec') path = os.path.expanduser(path) - self._config = helper.read_config(path, self._spec) + self._config = read_config(path, self._spec) del(self._config['format']) def get_contacts(self): diff --git a/alot/checks.py b/alot/checks.py deleted file mode 100644 index 693d3044..00000000 --- a/alot/checks.py +++ /dev/null @@ -1,21 +0,0 @@ -import mailbox -import re -from urlparse import urlparse - -def mail_container(value): - if not re.match(r'.*://.*', value): - raise VdtTypeError(value) - mburl = urlparse(value) - if mburl.scheme == 'mbox': - box = mailbox.mbox(mburl.path) - elif mburl.scheme == 'maildir': - box = mailbox.Maildir(mburl.path) - elif mburl.scheme == 'mh': - box = mailbox.MH(mburl.path) - elif mburl.scheme == 'babyl': - box = mailbox.Babyl(mburl.path) - elif mburl.scheme == 'mmdf': - box = mailbox.MMDF(mburl.path) - else: - raise VdtTypeError(value) - return box diff --git a/alot/errors.py b/alot/errors.py deleted file mode 100644 index 5409d315..00000000 --- a/alot/errors.py +++ /dev/null @@ -1,4 +0,0 @@ - - -class ConfigError(Exception): - pass diff --git a/alot/helper.py b/alot/helper.py index 7588e5aa..20751214 100644 --- a/alot/helper.py +++ b/alot/helper.py @@ -19,7 +19,7 @@ import StringIO import logging from configobj import ConfigObj, ConfigObjError, flatten_errors from validate import Validator -from alot.errors import ConfigError +from alot.settings.errors import ConfigError def safely_get(clb, E, on_error=''): @@ -399,40 +399,3 @@ def humanize_size(size): if size / factor < 1024: return format_string % (float(size) / factor) return format_string % (size / factor) - - -def read_config(configpath=None, specpath=None, checks={}): - """ - get a (validated) config object for given config file path. - - :param configpath: path to config-file - :type configpath: str - :param specpath: path to spec-file - :type specpath: str - :param checks: custom checks to use for validator. - see `validate docs `_ - :type checks: dict str->callable, - :rtype: `configobj.ConfigObj` - """ - try: - config = ConfigObj(infile=configpath, configspec=specpath, - file_error=True, encoding='UTF8') - except (ConfigObjError, IOError), e: - raise ConfigError('Could not read "%s": %s' % (configpath, e)) - - if specpath: - validator = Validator() - validator.functions.update(checks) - results = config.validate(validator) - - if results != True: - error_msg = 'Validation errors occurred:\n' - for (section_list, key, _) in flatten_errors(config, results): - if key is not None: - msg = 'key "%s" in section "%s" failed validation' - msg = msg % (key, ', '.join(section_list)) - else: - msg = 'section "%s" is malformed' % ', '.join(section_list) - error_msg += msg + '\n' - raise ConfigError(error_msg) - return config diff --git a/alot/settings.py b/alot/settings.py deleted file mode 100644 index 7fcea787..00000000 --- a/alot/settings.py +++ /dev/null @@ -1,398 +0,0 @@ -import imp -import os -import re -import mailcap -import logging -import urwid -from urwid import AttrSpec, AttrSpecError -from configobj import ConfigObj, Section - -from account import SendmailAccount, MatchSdtoutAddressbook, AbookAddressBook - -from alot.errors import ConfigError -from alot.helper import read_config -from checks import mail_container - -DEFAULTSPATH = os.path.join(os.path.dirname(__file__), 'defaults') - - -class Theme(object): - """Colour theme""" - def __init__(self, path): - """ - :param path: path to theme file - :type path: str - """ - self._spec = os.path.join(DEFAULTSPATH, 'theme.spec') - self._config = read_config(path, self._spec) - self.attributes = self._parse_attributes(self._config) - - def _parse_attributes(self, c): - """ - parse a (previously validated) valid theme file - into urwid AttrSpec attributes for internal use. - - :param c: config object for theme file - :type c: `configobj.ConfigObj` - :raises: `ConfigError` - """ - - attributes = {} - for sec in c.sections: - try: - colours = int(sec) - except ValueError: - err_msg = 'section name %s is not a valid colour mode' - raise ConfigError(err_msg % sec) - attributes[colours] = {} - for mode in c[sec].sections: - attributes[colours][mode] = {} - for themable in c[sec][mode].sections: - block = c[sec][mode][themable] - fg = block['fg'] - if colours == 1: - bg = 'default' - else: - bg = block['bg'] - if colours == 256: - fg = fg or c['16'][mode][themable][fg] - bg = bg or c['16'][mode][themable][bg] - try: - att = AttrSpec(fg, bg, colours) - except AttrSpecError, e: - raise ConfigError(e) - attributes[colours][mode][themable] = att - return attributes - - def get_attribute(self, mode, name, colourmode): - """ - returns requested attribute - - :param mode: ui-mode (e.g. `search`,`thread`...) - :type mode: str - :param name: identifier of the atttribute - :type name: str - :param colourmode: colour mode; in [1, 16, 256] - :type colourmode: int - """ - return self.attributes[colourmode][mode][name] - - -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) - self._bindings = read_config(os.path.join(DEFAULTSPATH, 'bindings')) - - 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}) - 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) - self._theme = Theme(theme_path) - - 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): - """ - look up global config values from alot's config - - :param key: key to look up - :type key: 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 - 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): - """ - 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 - :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] - return value - - def get_theming_attribute(self, mode, name): - """ - looks up theming attribute - - :param mode: ui-mode (e.g. `search`,`thread`...) - :type mode: str - :param name: identifier of the atttribute - :type name: str - """ - colours = int(self._config.get('colourmode')) - return self._theme.get_attribute(mode, name, colours) - - def get_tagstring_representation(self, tag): - """ - looks up user's preferred way to represent a given tagstring - - This returns a dictionary mapping - 'normal' and 'focussed' to `urwid.AttrSpec` sttributes, - and 'translated' to an alternative string representation - """ - colours = int(self._config.get('colourmode')) - # default attributes: normal and focussed - default = self._theme.get_attribute('global', 'tag', colours) - default_f = self._theme.get_attribute('global', 'tag_focus', colours) - for sec in self._config['tags'].sections: - if re.match('^' + sec + '$', tag): - fg = self._config['tags'][sec]['fg'] or default.foreground - bg = self._config['tags'][sec]['bg'] or default.background - try: - normal = urwid.AttrSpec(fg, bg, colours) - except AttrSpecError: - normal = default - focus_fg = self._config['tags'][sec]['focus_fg'] - focus_fg = focus_fg or default_f.foreground - focus_bg = self._config['tags'][sec]['focus_bg'] - focus_bg = focus_bg or default_f.background - try: - focussed = urwid.AttrSpec(focus_fg, focus_bg, colours) - except AttrSpecError: - focussed = default_f - - hidden = self._config['tags'][sec]['hidden'] or False - - translated = self._config['tags'][sec]['translated'] or tag - translation = self._config['tags'][sec]['translation'] - if translation: - translated = re.sub(translation[0], translation[1], tag) - break - else: - normal = default - focussed = default_f - hidden = False - translated = tag - - return {'normal': normal, 'focussed': focussed, - 'hidden': hidden, '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: - cmdline = bindings[mode][key] - 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 get_mime_handler(self, mime_type, key='view', interactive=True): - """ - get shellcomand defined in the users `mailcap` as handler for files of - given `mime_type`. - - :param mime_type: file type - :type mime_type: str - :param key: identifies one of possibly many commands for this type by - naming the intended usage, e.g. 'edit' or 'view'. Defaults - to 'view'. - :type key: str - :param interactive: choose the "interactive session" handler rather - than the "print to stdout and immediately return" - handler - :type interactive: bool - """ - if interactive: - mc_tuple = mailcap.findmatch(self._mailcaps, mime_type, key=key) - else: - mc_tuple = mailcap.findmatch(self._mailcaps, mime_type, - key='copiousoutput') - if mc_tuple: - if mc_tuple[1]: - return mc_tuple[1][key] - else: - return None - - -settings = SettingsManager() diff --git a/alot/settings/__init__.py b/alot/settings/__init__.py new file mode 100644 index 00000000..593fbae2 --- /dev/null +++ b/alot/settings/__init__.py @@ -0,0 +1,398 @@ +import imp +import os +import re +import mailcap +import logging +import urwid +from urwid import AttrSpec, AttrSpecError +from configobj import ConfigObj, Section + +from alot.account import SendmailAccount, MatchSdtoutAddressbook, AbookAddressBook + +from errors import ConfigError +from utils import read_config +from checks import mail_container + +DEFAULTSPATH = os.path.join(os.path.dirname(__file__), '..', 'defaults') + + +class Theme(object): + """Colour theme""" + def __init__(self, path): + """ + :param path: path to theme file + :type path: str + """ + self._spec = os.path.join(DEFAULTSPATH, 'theme.spec') + self._config = read_config(path, self._spec) + self.attributes = self._parse_attributes(self._config) + + def _parse_attributes(self, c): + """ + parse a (previously validated) valid theme file + into urwid AttrSpec attributes for internal use. + + :param c: config object for theme file + :type c: `configobj.ConfigObj` + :raises: `ConfigError` + """ + + attributes = {} + for sec in c.sections: + try: + colours = int(sec) + except ValueError: + err_msg = 'section name %s is not a valid colour mode' + raise ConfigError(err_msg % sec) + attributes[colours] = {} + for mode in c[sec].sections: + attributes[colours][mode] = {} + for themable in c[sec][mode].sections: + block = c[sec][mode][themable] + fg = block['fg'] + if colours == 1: + bg = 'default' + else: + bg = block['bg'] + if colours == 256: + fg = fg or c['16'][mode][themable][fg] + bg = bg or c['16'][mode][themable][bg] + try: + att = AttrSpec(fg, bg, colours) + except AttrSpecError, e: + raise ConfigError(e) + attributes[colours][mode][themable] = att + return attributes + + def get_attribute(self, mode, name, colourmode): + """ + returns requested attribute + + :param mode: ui-mode (e.g. `search`,`thread`...) + :type mode: str + :param name: identifier of the atttribute + :type name: str + :param colourmode: colour mode; in [1, 16, 256] + :type colourmode: int + """ + return self.attributes[colourmode][mode][name] + + +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) + self._bindings = read_config(os.path.join(DEFAULTSPATH, 'bindings')) + + 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}) + 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) + self._theme = Theme(theme_path) + + 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): + """ + look up global config values from alot's config + + :param key: key to look up + :type key: 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 + 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): + """ + 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 + :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] + return value + + def get_theming_attribute(self, mode, name): + """ + looks up theming attribute + + :param mode: ui-mode (e.g. `search`,`thread`...) + :type mode: str + :param name: identifier of the atttribute + :type name: str + """ + colours = int(self._config.get('colourmode')) + return self._theme.get_attribute(mode, name, colours) + + def get_tagstring_representation(self, tag): + """ + looks up user's preferred way to represent a given tagstring + + This returns a dictionary mapping + 'normal' and 'focussed' to `urwid.AttrSpec` sttributes, + and 'translated' to an alternative string representation + """ + colours = int(self._config.get('colourmode')) + # default attributes: normal and focussed + default = self._theme.get_attribute('global', 'tag', colours) + default_f = self._theme.get_attribute('global', 'tag_focus', colours) + for sec in self._config['tags'].sections: + if re.match('^' + sec + '$', tag): + fg = self._config['tags'][sec]['fg'] or default.foreground + bg = self._config['tags'][sec]['bg'] or default.background + try: + normal = urwid.AttrSpec(fg, bg, colours) + except AttrSpecError: + normal = default + focus_fg = self._config['tags'][sec]['focus_fg'] + focus_fg = focus_fg or default_f.foreground + focus_bg = self._config['tags'][sec]['focus_bg'] + focus_bg = focus_bg or default_f.background + try: + focussed = urwid.AttrSpec(focus_fg, focus_bg, colours) + except AttrSpecError: + focussed = default_f + + hidden = self._config['tags'][sec]['hidden'] or False + + translated = self._config['tags'][sec]['translated'] or tag + translation = self._config['tags'][sec]['translation'] + if translation: + translated = re.sub(translation[0], translation[1], tag) + break + else: + normal = default + focussed = default_f + hidden = False + translated = tag + + return {'normal': normal, 'focussed': focussed, + 'hidden': hidden, '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: + cmdline = bindings[mode][key] + 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 get_mime_handler(self, mime_type, key='view', interactive=True): + """ + get shellcomand defined in the users `mailcap` as handler for files of + given `mime_type`. + + :param mime_type: file type + :type mime_type: str + :param key: identifies one of possibly many commands for this type by + naming the intended usage, e.g. 'edit' or 'view'. Defaults + to 'view'. + :type key: str + :param interactive: choose the "interactive session" handler rather + than the "print to stdout and immediately return" + handler + :type interactive: bool + """ + if interactive: + mc_tuple = mailcap.findmatch(self._mailcaps, mime_type, key=key) + else: + mc_tuple = mailcap.findmatch(self._mailcaps, mime_type, + key='copiousoutput') + if mc_tuple: + if mc_tuple[1]: + return mc_tuple[1][key] + else: + return None + + +settings = SettingsManager() diff --git a/alot/settings/checks.py b/alot/settings/checks.py new file mode 100644 index 00000000..693d3044 --- /dev/null +++ b/alot/settings/checks.py @@ -0,0 +1,21 @@ +import mailbox +import re +from urlparse import urlparse + +def mail_container(value): + if not re.match(r'.*://.*', value): + raise VdtTypeError(value) + mburl = urlparse(value) + if mburl.scheme == 'mbox': + box = mailbox.mbox(mburl.path) + elif mburl.scheme == 'maildir': + box = mailbox.Maildir(mburl.path) + elif mburl.scheme == 'mh': + box = mailbox.MH(mburl.path) + elif mburl.scheme == 'babyl': + box = mailbox.Babyl(mburl.path) + elif mburl.scheme == 'mmdf': + box = mailbox.MMDF(mburl.path) + else: + raise VdtTypeError(value) + return box diff --git a/alot/settings/errors.py b/alot/settings/errors.py new file mode 100644 index 00000000..5409d315 --- /dev/null +++ b/alot/settings/errors.py @@ -0,0 +1,4 @@ + + +class ConfigError(Exception): + pass -- cgit v1.2.3