Using backend specific parameter definitions to store backend settings.

This commit is contained in:
Timo Kankare
2016-09-20 22:06:48 +03:00
parent eba3c1b933
commit 068f6339b4
4 changed files with 168 additions and 30 deletions

View File

@@ -39,32 +39,42 @@ def _str_to_folders(folders_str):
return folders
def _folders_to_str(folders):
return json.dumps(folders)
def _str_to_bool(string):
return bool(int(string))
Param = namedtuple('Param', ['param_name', 'option_name', 'from_str', 'default_value'])
def _bool_to_str(b):
return str(int(b))
Param = namedtuple('Param',
['param_name', 'option_name', 'from_str', 'to_str', 'default_value']
)
Backend = namedtuple('Backend', ['backend_class', 'params'])
_backends = {
'imap' : Backend(IMAPMailboxBackend, [
Param('user', 'user', str, ''),
Param('password', 'password', str, ''),
Param('server', 'server', str, ''),
Param('port', 'port', str, ''),
Param('ssl', 'ssl', _str_to_bool, True),
Param('imap', 'imap', _str_to_bool, True),
Param('idle', 'idle', _str_to_bool, True),
Param('folders', 'folder', _str_to_folders, []),
Param('user', 'user', str, str, ''),
Param('password', 'password', str, str, ''),
Param('server', 'server', str, str, ''),
Param('port', 'port', str, str, ''),
Param('ssl', 'ssl', _str_to_bool, _bool_to_str, True),
Param('imap', 'imap', _str_to_bool, _bool_to_str, True),
Param('idle', 'idle', _str_to_bool, _bool_to_str, True),
Param('folders', 'folder', _str_to_folders, _folders_to_str, []),
]),
'pop3' : Backend(POP3MailboxBackend, [
Param('user', 'user', str, ''),
Param('password', 'password', str, ''),
Param('server', 'server', str, ''),
Param('port', 'port', str, ''),
Param('ssl', 'ssl', _str_to_bool, True),
Param('imap', 'imap', _str_to_bool, False),
Param('idle', 'idle', _str_to_bool, False),
Param('user', 'user', str, str, ''),
Param('password', 'password', str, str, ''),
Param('server', 'server', str, str, ''),
Param('port', 'port', str, str, ''),
Param('ssl', 'ssl', _str_to_bool, _bool_to_str, True),
Param('imap', 'imap', _str_to_bool, _bool_to_str, False),
Param('idle', 'idle', _str_to_bool, _bool_to_str, False),
]),
}

View File

@@ -25,7 +25,6 @@
#
import logging
import json
from Mailnag.backends import create_backend, get_mailbox_parameter_specs
account_defaults = {
@@ -49,7 +48,7 @@ CREDENTIAL_KEY = 'Mailnag password for %s://%s@%s'
#
class Account:
def __init__(self, enabled = False, name = '', user = '', \
password = '', oauth2string = '', server = '', port = '', ssl = True, imap = True, idle = True, folders = [], backend = None, mailbox_type = None):
password = '', oauth2string = '', server = '', port = '', ssl = True, imap = True, idle = True, folders = [], backend = None, mailbox_type = None, **kw):
self.enabled = enabled # bool
if mailbox_type:
@@ -67,6 +66,27 @@ class Account:
self.idle = idle # bool
self.folders = folders
self.backend = backend
self._rest_of_config = kw
def get_config(self):
"""Return account's configuration as a dict."""
config = {
'enabled': self.enabled,
'mailbox_type': self.mailbox_type,
'name': self.name,
'user': self.user,
'password': self.password,
'oauth2string': self.oauth2string,
'server': self.server,
'port': self.port,
'ssl': self.ssl,
'imap': self.imap,
'idle': self.idle,
'folders': self.folders,
}
config.update(self._rest_of_config)
return config
def open(self):
@@ -240,20 +260,18 @@ class AccountManager:
cfg.set(section_name, 'enabled', int(acc.enabled))
cfg.set(section_name, 'type', acc.mailbox_type)
cfg.set(section_name, 'name', acc.name)
cfg.set(section_name, 'user', acc.user)
cfg.set(section_name, 'password', '')
cfg.set(section_name, 'server', acc.server)
cfg.set(section_name, 'port', acc.port)
cfg.set(section_name, 'ssl', int(acc.ssl))
cfg.set(section_name, 'imap', int(acc.imap))
cfg.set(section_name, 'idle', int(acc.idle))
cfg.set(section_name, 'folder', json.dumps(acc.folders))
config = acc.get_config()
option_spec = get_mailbox_parameter_specs(acc.mailbox_type)
# TODO: Setting password to credentials is mailbox specific.
# Every backend do not have or need password.
if self._credentialstore != None:
protocol = 'imap' if acc.imap else 'pop'
self._credentialstore.set(CREDENTIAL_KEY % (protocol, acc.user, acc.server), acc.password)
else:
cfg.set(section_name, 'password', acc.password)
config['password'] = ''
self._set_cfg_options(cfg, section_name, config, option_spec)
i = i + 1
@@ -283,3 +301,12 @@ class AccountManager:
value = default_value
return value
def _set_cfg_options(self, cfg, section_name, options, option_spec):
for s in option_spec:
if s.to_str and s.param_name in options:
value = s.to_str(options[s.param_name])
else:
value = s.default_value
cfg.set(section_name, s.option_name, value)

72
tests/test_account.py Normal file
View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
#
# test_account.py
#
# Copyright 2016 Timo Kankare <timo.kankare@iki.fi>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
"""Test cases for Account."""
from Mailnag.common.accounts import Account
def test_account_should_keep_configuration():
account = Account(enabled=True,
name='my name',
user='who',
password='secret',
oauth2string='who knows',
server='example.org',
port='1234',
ssl=True,
imap=True,
idle=True,
folders=['a', 'b'],
mailbox_type='mybox')
config = account.get_config()
expected_config = {
'enabled': True,
'name': 'my name',
'user': 'who',
'password': 'secret',
'oauth2string': 'who knows',
'server': 'example.org',
'port': '1234',
'ssl': True,
'imap': True,
'idle': True,
'folders': ['a', 'b'],
'mailbox_type': 'mybox',
}
assert expected_config == config
def test_account_config_should_always_contain_certain_values():
account = Account()
config = account.get_config()
assert 'enabled' in config
assert 'name' in config
assert 'mailbox_type' in config
def test_account_should_configurable_with_any_parameters():
account = Account(weird='odd', odd='weird')
config = account.get_config()
assert config['weird'] == 'odd'
assert config['odd'] == 'weird'

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# test_backends.py
# test_accountmanager.py
#
# Copyright 2016 Timo Kankare <timo.kankare@iki.fi>
#
@@ -168,3 +168,32 @@ def test_pop3_config_defaults(config):
}
assert expected_options == options
def test_imap_config_values_should_be_stored():
am = AccountManager()
option_spec = get_mailbox_parameter_specs('imap')
options = {
'user': 'you',
'password': '',
'server': 'imap.example.org',
'port': '',
'ssl': True,
'imap': True,
'idle': True,
'folders': ['a', 'b'],
}
config = RawConfigParser()
config.add_section('account1')
am._set_cfg_options(config, 'account1', options, option_spec)
expected_config_items = [
('user', 'you'),
('password', ''),
('server', 'imap.example.org'),
('port', ''),
('ssl', '1'),
('imap', '1'),
('idle', '1'),
('folder', '["a", "b"]'),
]
assert set(expected_config_items) == set(config.items('account1'))