new class BackendConfig to manage backend configs

This commit is contained in:
Romain Bignon 2011-05-21 10:26:57 +02:00
commit cb1372b99f
23 changed files with 234 additions and 171 deletions

View file

@ -21,8 +21,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import Value
from .browser import ArteBrowser from .browser import ArteBrowser
from .video import ArteVideo from .video import ArteVideo
@ -38,13 +38,13 @@ class ArteBackend(BaseBackend, ICapVideo):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'Arte french TV' DESCRIPTION = 'Arte french TV'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('lang', label='Lang of videos', CONFIG = BackendConfig(Value('lang', label='Lang of videos',
choices={'fr': 'French', 'de': 'Deutsch', 'en': 'English'}, default='fr'), choices={'fr': 'French', 'de': 'Deutsch', 'en': 'English'}, default='fr'),
Value('quality', label='Quality of videos', choices=['hd', 'sd'], default='hd')) Value('quality', label='Quality of videos', choices=['hd', 'sd'], default='hd'))
BROWSER = ArteBrowser BROWSER = ArteBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(lang=self.config['lang'], quality=self.config['quality']) return self.create_browser(lang=self.config['lang'].get(), quality=self.config['quality'].get())
def get_video(self, _id): def get_video(self, _id):
with self.browser: with self.browser:

View file

@ -30,9 +30,9 @@ from weboob.capabilities.messages import ICapMessages, ICapMessagesPost, Message
from weboob.capabilities.dating import ICapDating, OptimizationNotFound from weboob.capabilities.dating import ICapDating, OptimizationNotFound
from weboob.capabilities.contact import ICapContact, Contact, ContactPhoto, ProfileNode, Query, QueryError from weboob.capabilities.contact import ICapContact, Contact, ContactPhoto, ProfileNode, Query, QueryError
from weboob.capabilities.account import ICapAccount, StatusField from weboob.capabilities.account import ICapAccount, StatusField
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.browser import BrowserUnavailable from weboob.tools.browser import BrowserUnavailable
from weboob.tools.value import Value, ValuesDict, ValueBool from weboob.tools.value import Value, ValuesDict, ValueBool, ValueBackendPassword
from weboob.tools.log import getLogger from weboob.tools.log import getLogger
from .captcha import CaptchaError from .captcha import CaptchaError
@ -55,10 +55,10 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = u"“Adopte un mec” french dating website" DESCRIPTION = u"“Adopte un mec” french dating website"
CONFIG = ValuesDict(Value('username', label='Username'), CONFIG = BackendConfig(Value('username', label='Username'),
Value('password', label='Password', masked=True), ValueBackendPassword('password', label='Password'),
ValueBool('antispam', label='Enable anti-spam', default=False), ValueBool('antispam', label='Enable anti-spam', default=False),
ValueBool('baskets', label='Get baskets with new messages', default=True)) ValueBool('baskets', label='Get baskets with new messages', default=True))
STORAGE = {'profiles_walker': {'viewed': []}, STORAGE = {'profiles_walker': {'viewed': []},
'priority_connection': {'config': {}, 'fakes': {}}, 'priority_connection': {'config': {}, 'fakes': {}},
'queries_queue': {'queue': []}, 'queries_queue': {'queue': []},
@ -70,13 +70,13 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
BaseBackend.__init__(self, *args, **kwargs) BaseBackend.__init__(self, *args, **kwargs)
if self.config['antispam']: if self.config['antispam'].get():
self.antispam = AntiSpam() self.antispam = AntiSpam()
else: else:
self.antispam = None self.antispam = None
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['username'], self.config['password']) return self.create_browser(self.config['username'].get(), self.config['password'].get())
def report_spam(self, id, suppr_id=None): def report_spam(self, id, suppr_id=None):
if suppr_id: if suppr_id:
@ -215,7 +215,7 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
if m.flags & m.IS_UNREAD: if m.flags & m.IS_UNREAD:
yield m yield m
if not self.config['baskets']: if not self.config['baskets'].get():
return return
# Send mail when someone added me in her basket. # Send mail when someone added me in her basket.
@ -437,18 +437,18 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
@param account an Account object which describe the account to create @param account an Account object which describe the account to create
""" """
browser = None browser = None
bday, bmonth, byear = account.properties['birthday'].value.split('/', 2) bday, bmonth, byear = account.properties['birthday'].get().split('/', 2)
while not browser: while not browser:
try: try:
browser = klass.BROWSER(account.properties['username'].value) browser = klass.BROWSER(account.properties['username'].get())
browser.register(password= account.properties['password'].value, browser.register(password= account.properties['password'].get(),
sex= (0 if account.properties['sex'].value == 'm' else 1), sex= (0 if account.properties['sex'].get() == 'm' else 1),
birthday_d= int(bday), birthday_d= int(bday),
birthday_m= int(bmonth), birthday_m= int(bmonth),
birthday_y= int(byear), birthday_y= int(byear),
zipcode= account.properties['zipcode'].value, zipcode= account.properties['zipcode'].get(),
country= account.properties['country'].value, country= account.properties['country'].get(),
godfather= account.properties['godfather'].value) godfather= account.properties['godfather'].get())
except CaptchaError: except CaptchaError:
getLogger('aum').info('Unable to resolve captcha. Retrying...') getLogger('aum').info('Unable to resolve captcha. Retrying...')
browser = None browser = None

View file

@ -22,8 +22,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.bank import ICapBank, AccountNotFound, Account, Recipient from weboob.capabilities.bank import ICapBank, AccountNotFound, Account, Recipient
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import Value, ValueBackendPassword
from .browser import BNPorc from .browser import BNPorc
@ -38,29 +38,27 @@ class BNPorcBackend(BaseBackend, ICapBank):
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = 'BNP Paribas french bank\' website' DESCRIPTION = 'BNP Paribas french bank\' website'
CONFIG = ValuesDict(Value('login', label='Account ID'), CONFIG = BackendConfig(Value('login', label='Account ID'),
Value('password', label='Password', masked=True), ValueBackendPassword('password', label='Password', regexp='^(\d{6}|)$'),
Value('rotating_password', ValueBackendPassword('rotating_password',
label='Password to set when the allowed uses are exhausted (6 digits)', label='Password to set when the allowed uses are exhausted (6 digits)',
default='', masked=True, regexp='^(\d{6}|)$'))
regexp='^(\d{6}|)$'))
BROWSER = BNPorc BROWSER = BNPorc
def create_default_browser(self): def create_default_browser(self):
if self.config['rotating_password'].isdigit() and len(self.config['rotating_password']) == 6: if self.config['rotating_password'].get().isdigit() and len(self.config['rotating_password'].get()) == 6:
rotating_password = self.config['rotating_password'] rotating_password = self.config['rotating_password'].get()
else: else:
rotating_password = None rotating_password = None
return self.create_browser(self.config['login'], return self.create_browser(self.config['login'].get(),
self.config['password'], self.config['password'].get(),
password_changed_cb=self._password_changed_cb, password_changed_cb=self._password_changed_cb,
rotating_password=rotating_password) rotating_password=rotating_password)
def _password_changed_cb(self, old, new): def _password_changed_cb(self, old, new):
new_settings = {'password': new, self.config['password'].set(new)
'rotating_password': old, self.config['rotating_password'].set(old)
} self.config.save()
self.weboob.backends_config.edit_backend(self.name, self.NAME, new_settings)
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts_list(): for account in self.browser.get_accounts_list():

View file

@ -21,8 +21,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.messages import CantSendMessage, ICapMessages, ICapMessagesPost from weboob.capabilities.messages import CantSendMessage, ICapMessages, ICapMessagesPost
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import BouyguesBrowser from .browser import BouyguesBrowser
@ -37,13 +37,13 @@ class BouyguesBackend(BaseBackend, ICapMessages, ICapMessagesPost):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'Bouygues french mobile phone provider' DESCRIPTION = 'Bouygues french mobile phone provider'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('login', label='Login'), CONFIG = BackendConfig(Value('login', label='Login'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = BouyguesBrowser BROWSER = BouyguesBrowser
ACCOUNT_REGISTER_PROPERTIES = None ACCOUNT_REGISTER_PROPERTIES = None
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['login'], self.config['password']) return self.create_browser(self.config['login'].get(), self.config['password'].get())
def post_message(self, message): def post_message(self, message):
if not message.content.strip(): if not message.content.strip():

View file

@ -19,8 +19,8 @@
from weboob.capabilities.bank import ICapBank, AccountNotFound from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import BPBrowser from .browser import BPBrowser
@ -35,12 +35,12 @@ class BPBackend(BaseBackend, ICapBank):
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = u'La banque postale, French bank' DESCRIPTION = u'La banque postale, French bank'
CONFIG = ValuesDict(Value('login', label='Account ID'), CONFIG = BackendConfig(Value('login', label='Account ID'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = BPBrowser BROWSER = BPBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['login'], self.config['password']) return self.create_browser(self.config['login'].get(), self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts_list(): for account in self.browser.get_accounts_list():
@ -56,7 +56,7 @@ class BPBackend(BaseBackend, ICapBank):
def iter_history(self, account): def iter_history(self, account):
for history in self.browser.get_history(account): for history in self.browser.get_history(account):
yield history yield history
def transfer(self, id_from, id_to, amount, reason=None): def transfer(self, id_from, id_to, amount, reason=None):
from_account = self.get_account(id_from) from_account = self.get_account(id_from)
to_account = self.get_account(id_to) to_account = self.get_account(id_to)

View file

@ -21,8 +21,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import Value
from .browser import CanalplusBrowser from .browser import CanalplusBrowser
from .pages import CanalplusVideo from .pages import CanalplusVideo
@ -40,11 +40,11 @@ class CanalplusBackend(BaseBackend, ICapVideo, ICapCollection):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'Canal plus french TV' DESCRIPTION = 'Canal plus french TV'
LICENSE = 'GPLv3' LICENSE = 'GPLv3'
CONFIG = ValuesDict(Value('quality', label='Quality of videos', choices=['hd', 'sd'], default='hd')) CONFIG = BackendConfig(Value('quality', label='Quality of videos', choices=['hd', 'sd'], default='hd'))
BROWSER = CanalplusBrowser BROWSER = CanalplusBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(quality=self.config['quality']) return self.create_browser(quality=self.config['quality'].get())
def iter_search_results(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def iter_search_results(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:

View file

@ -19,9 +19,9 @@
from weboob.capabilities.bank import ICapBank, AccountNotFound from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.ordereddict import OrderedDict from weboob.tools.ordereddict import OrderedDict
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import Cragr from .browser import Cragr
@ -72,13 +72,15 @@ class CragrBackend(BaseBackend, ICapBank):
'm.ca-toulouse31.fr': u'Toulouse 31', # m.ca-toulousain.fr redirects here 'm.ca-toulouse31.fr': u'Toulouse 31', # m.ca-toulousain.fr redirects here
'm.ca-tourainepoitou.fr': u'Tourraine Poitou', 'm.ca-tourainepoitou.fr': u'Tourraine Poitou',
}.iteritems())]) }.iteritems())])
CONFIG = ValuesDict(Value('website', label='Website to use', choices=website_choices), CONFIG = BackendConfig(Value('website', label='Website to use', choices=website_choices),
Value('login', label='Account ID'), Value('login', label='Account ID'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = Cragr BROWSER = Cragr
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['website'], self.config['login'], self.config['password']) return self.create_browser(self.config['website'].get(),
self.config['login'].get(),
self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts_list(): for account in self.browser.get_accounts_list():

View file

@ -19,8 +19,8 @@
from weboob.capabilities.bank import ICapBank, AccountNotFound from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import CreditMutuelBrowser from .browser import CreditMutuelBrowser
@ -35,12 +35,12 @@ class CreditMutuelBackend(BaseBackend, ICapBank):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = u'Crédit Mutuel french bank' DESCRIPTION = u'Crédit Mutuel french bank'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('login', label='Account ID', regexp='^\d{1,13}\w$'), CONFIG = BackendConfig(Value('login', label='Account ID', regexp='^\d{1,13}\w$'),
Value('password', label='Password of account', masked=True)) ValueBackendPassword('password', label='Password of account'))
BROWSER = CreditMutuelBrowser BROWSER = CreditMutuelBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser( self.config['login'], self.config['password']) return self.create_browser(self.config['login'].get(), self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts_list(): for account in self.browser.get_accounts_list():

View file

@ -20,9 +20,9 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.newsfeed import Newsfeed from weboob.tools.newsfeed import Newsfeed
from weboob.tools.value import Value, ValueBool, ValuesDict from weboob.tools.value import Value, ValueBool, ValueBackendPassword
from weboob.tools.misc import limit from weboob.tools.misc import limit
from weboob.capabilities.messages import ICapMessages, ICapMessagesPost, Message, Thread, CantSendMessage from weboob.capabilities.messages import ICapMessages, ICapMessagesPost, Message, Thread, CantSendMessage
from weboob.capabilities.content import ICapContent, Content from weboob.capabilities.content import ICapContent, Content
@ -41,14 +41,14 @@ class DLFPBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapContent):
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = "Da Linux French Page" DESCRIPTION = "Da Linux French Page"
CONFIG = ValuesDict(Value('username', label='Username', regexp='.+'), CONFIG = BackendConfig(Value('username', label='Username', regexp='.+'),
Value('password', label='Password', regexp='.+', masked=True), ValueBackendPassword('password', label='Password'),
ValueBool('get_news', label='Get newspapers', default=True), ValueBool('get_news', label='Get newspapers', default=True),
ValueBool('get_diaries', label='Get diaries', default=False), ValueBool('get_diaries', label='Get diaries', default=False),
ValueBool('get_polls', label='Get polls', default=False), ValueBool('get_polls', label='Get polls', default=False),
ValueBool('get_board', label='Get board', default=False), ValueBool('get_board', label='Get board', default=False),
ValueBool('get_wiki', label='Get wiki', default=False), ValueBool('get_wiki', label='Get wiki', default=False),
ValueBool('get_tracker', label='Get tracker', default=False)) ValueBool('get_tracker', label='Get tracker', default=False))
STORAGE = {'seen': {}} STORAGE = {'seen': {}}
BROWSER = DLFP BROWSER = DLFP
@ -61,7 +61,7 @@ class DLFPBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapContent):
} }
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['username'], self.config['password']) return self.create_browser(self.config['username'].get(), self.config['password'].get())
def deinit(self): def deinit(self):
# don't need to logout if the browser hasn't been used. # don't need to logout if the browser hasn't been used.
@ -76,7 +76,7 @@ class DLFPBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapContent):
def iter_threads(self): def iter_threads(self):
whats = set() whats = set()
for param, url in self.FEEDS.iteritems(): for param, url in self.FEEDS.iteritems():
if self.config[param]: if self.config[param].get():
whats.add(url) whats.add(url)
for what in whats: for what in whats:

View file

@ -21,9 +21,9 @@ from __future__ import with_statement
import re import re
from weboob.capabilities.gallery import ICapGallery from weboob.capabilities.gallery import ICapGallery
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.misc import ratelimit from weboob.tools.misc import ratelimit
from weboob.tools.value import Value, ValuesDict from weboob.tools.value import Value, ValueBackendPassword
from .browser import EHentaiBrowser from .browser import EHentaiBrowser
from .gallery import EHentaiGallery, EHentaiImage from .gallery import EHentaiGallery, EHentaiImage
@ -40,16 +40,18 @@ class EHentaiBackend(BaseBackend, ICapGallery):
DESCRIPTION = 'E-hentai galleries' DESCRIPTION = 'E-hentai galleries'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
BROWSER = EHentaiBrowser BROWSER = EHentaiBrowser
CONFIG = ValuesDict( CONFIG = BackendConfig(
Value('domain', label='Domain', default='g.e-hentai.org'), Value('domain', label='Domain', default='g.e-hentai.org'),
Value('username', label='Username', default=''), Value('username', label='Username', default=''),
Value('password', label='Password', default='', masked=True)) ValueBackendPassword('password', label='Password'))
def create_default_browser(self): def create_default_browser(self):
return self.create_browser( username = self.config['username'].get()
self.config['domain'], if username:
self.config['username'], password = self.config['password'].get()
self.config['password']) else:
password = None
return self.create_browser(self.config['domain'].get(), username, password)
def iter_search_results(self, pattern=None, sortby=None, max_results=None): def iter_search_results(self, pattern=None, sortby=None, max_results=None):
with self.browser: with self.browser:

View file

@ -21,8 +21,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.messages import ICapMessages, Message, Thread from weboob.capabilities.messages import ICapMessages, Message, Thread
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import Value, ValuesDict from weboob.tools.value import Value
from .browser import FourChan from .browser import FourChan
@ -37,7 +37,7 @@ class FourChanBackend(BaseBackend, ICapMessages):
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = '4chan website' DESCRIPTION = '4chan website'
CONFIG = ValuesDict(Value('boards', label='Boards to fetch')) CONFIG = BackendConfig(Value('boards', label='Boards to fetch'))
STORAGE = {'boards': {}} STORAGE = {'boards': {}}
BROWSER = FourChan BROWSER = FourChan
@ -100,7 +100,7 @@ class FourChanBackend(BaseBackend, ICapMessages):
return thread return thread
def iter_threads(self): def iter_threads(self):
for board in self.config['boards'].split(' '): for board in self.config['boards'].get().split(' '):
with self.browser: with self.browser:
threads = self.browser.get_threads(board) threads = self.browser.get_threads(board)
for thread in threads: for thread in threads:

View file

@ -18,8 +18,8 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.capabilities.torrent import ICapTorrent from weboob.capabilities.torrent import ICapTorrent
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import GazelleBrowser from .browser import GazelleBrowser
@ -34,15 +34,15 @@ class GazelleBackend(BaseBackend, ICapTorrent):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'gazelle bittorrent tracker' DESCRIPTION = 'gazelle bittorrent tracker'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('domain', label='Domain (example "ssl.what.cd")'), CONFIG = BackendConfig(Value('domain', label='Domain (example "ssl.what.cd")'),
Value('protocol', label='Protocol to use', choices=('http', 'https')), Value('protocol', label='Protocol to use', choices=('http', 'https')),
Value('username', label='Username'), Value('username', label='Username'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = GazelleBrowser BROWSER = GazelleBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['protocol'], self.config['domain'], return self.create_browser(self.config['protocol'].get(), self.config['domain'].get(),
self.config['username'], self.config['password']) self.config['username'].get(), self.config['password'].get())
def get_torrent(self, id): def get_torrent(self, id):
return self.browser.get_torrent(id) return self.browser.get_torrent(id)

View file

@ -21,8 +21,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.bank import ICapBank, AccountNotFound from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import LCLBrowser from .browser import LCLBrowser
@ -37,13 +37,15 @@ class LCLBackend(BaseBackend, ICapBank):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'Le Credit Lyonnais crappy french bank' DESCRIPTION = 'Le Credit Lyonnais crappy french bank'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('login', label='Account ID', regexp='^\d{1,6}\w$'), CONFIG = BackendConfig(Value('login', label='Account ID', regexp='^\d{1,6}\w$'),
Value('password', label='Password of account', masked=True), ValueBackendPassword('password', label='Password of account'),
Value('agency', label='Agency code', regexp='^\d{3,4}$')) Value('agency', label='Agency code', regexp='^\d{3,4}$'))
BROWSER = LCLBrowser BROWSER = LCLBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['agency'], self.config['login'], self.config['password']) return self.create_browser(self.config['agency'].get(),
self.config['login'].get(),
self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts_list(): for account in self.browser.get_accounts_list():

View file

@ -19,9 +19,9 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.capabilities.content import ICapContent, Content from weboob.capabilities.content import ICapContent, Content
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import MediawikiBrowser from .browser import MediawikiBrowser
@ -36,14 +36,21 @@ class MediawikiBackend(BaseBackend, ICapContent):
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = 'Mediawiki wiki software application' DESCRIPTION = 'Mediawiki wiki software application'
CONFIG = ValuesDict(Value('url', label='URL of the Mediawiki website', default='http://en.wikipedia.org/'), CONFIG = BackendConfig(Value('url', label='URL of the Mediawiki website', default='http://en.wikipedia.org/'),
Value('apiurl', label='URL of the Mediawiki website\'s API', default='http://en.wikipedia.org/w/api.php'), Value('apiurl', label='URL of the Mediawiki website\'s API', default='http://en.wikipedia.org/w/api.php'),
Value('username', label='Login', default=''), Value('username', label='Login', default=''),
Value('password', label='Password', default='', masked=True)) ValueBackendPassword('password', label='Password', default=''))
BROWSER = MediawikiBrowser BROWSER = MediawikiBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['url'], self.config['apiurl'], self.config['username'], self.config['password']) username = self.config['username'].get()
if len(username) > 0:
password = self.config['password'].get()
else:
password = None
return self.create_browser(self.config['url'].get(),
self.config['apiurl'].get(),
username, password)
def get_content(self, _id): def get_content(self, _id):
_id = _id.replace(' ', '_').encode('utf-8') _id = _id.replace(' ', '_').encode('utf-8')

View file

@ -18,10 +18,10 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.capabilities.messages import ICapMessages, Message, Thread from weboob.capabilities.messages import ICapMessages, Message, Thread
from weboob.tools.newsfeed import Newsfeed from weboob.tools.newsfeed import Newsfeed
from weboob.tools.value import Value, ValuesDict from weboob.tools.value import Value
__all__ = ['NewsfeedBackend'] __all__ = ['NewsfeedBackend']
@ -34,12 +34,12 @@ class NewsfeedBackend(BaseBackend, ICapMessages):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = "Loads RSS and Atom feeds from any website" DESCRIPTION = "Loads RSS and Atom feeds from any website"
LICENSE = "AGPLv3+" LICENSE = "AGPLv3+"
CONFIG = ValuesDict(Value('url', label="Atom/RSS feed's url")) CONFIG = BackendConfig(Value('url', label="Atom/RSS feed's url"))
STORAGE = {'seen': []} STORAGE = {'seen': []}
def iter_threads(self): def iter_threads(self):
for article in Newsfeed(self.config["url"]).iter_entries(): for article in Newsfeed(self.config['url'].get()).iter_entries():
yield self.get_thread(article.id, article) yield self.get_thread(article.id, article)
def get_thread(self, id, entry=None): def get_thread(self, id, entry=None):
@ -50,7 +50,7 @@ class NewsfeedBackend(BaseBackend, ICapMessages):
thread = Thread(id) thread = Thread(id)
if entry is None: if entry is None:
entry = Newsfeed(self.config["url"]).get_entry(id) entry = Newsfeed(self.config['url'].get()).get_entry(id)
if entry is None: if entry is None:
return None return None

View file

@ -22,8 +22,8 @@ from __future__ import with_statement
from weboob.capabilities.messages import CantSendMessage, ICapMessages, ICapMessagesPost from weboob.capabilities.messages import CantSendMessage, ICapMessages, ICapMessagesPost
from weboob.capabilities.account import ICapAccount, StatusField from weboob.capabilities.account import ICapAccount, StatusField
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import OrangeBrowser from .browser import OrangeBrowser
@ -38,15 +38,15 @@ class OrangeBackend(BaseBackend, ICapAccount, ICapMessages, ICapMessagesPost):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'Orange french mobile phone provider' DESCRIPTION = 'Orange french mobile phone provider'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('login', label='Login'), CONFIG = BackendConfig(Value('login', label='Login'),
Value('password', label='Password', masked=True), ValueBackendPassword('password', label='Password'),
Value('phonenumber', Label='Phone number') Value('phonenumber', Label='Phone number')
) )
BROWSER = OrangeBrowser BROWSER = OrangeBrowser
ACCOUNT_REGISTER_PROPERTIES = None ACCOUNT_REGISTER_PROPERTIES = None
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['login'], self.config['password']) return self.create_browser(self.config['login'].get(), self.config['password'].get())
def get_account_status(self): def get_account_status(self):
with self.browser: with self.browser:
@ -57,4 +57,4 @@ class OrangeBackend(BaseBackend, ICapAccount, ICapMessages, ICapMessagesPost):
if not message.content.strip(): if not message.content.strip():
raise CantSendMessage(u'Message content is empty.') raise CantSendMessage(u'Message content is empty.')
with self.browser: with self.browser:
self.browser.post_message(message, self.config['phonenumber']) self.browser.post_message(message, self.config['phonenumber'].get())

View file

@ -21,9 +21,9 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.tools.capabilities.paste import BasePasteBackend from weboob.tools.capabilities.paste import BasePasteBackend
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.capabilities.base import NotLoaded from weboob.capabilities.base import NotLoaded
from weboob.tools.value import Value, ValuesDict from weboob.tools.value import Value, ValueBackendPassword
from .browser import PastebinBrowser from .browser import PastebinBrowser
from .paste import PastebinPaste from .paste import PastebinPaste
@ -40,10 +40,10 @@ class PastebinBackend(BaseBackend, BasePasteBackend):
DESCRIPTION = 'Pastebin paste tool' DESCRIPTION = 'Pastebin paste tool'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
BROWSER = PastebinBrowser BROWSER = PastebinBrowser
CONFIG = ValuesDict( CONFIG = BackendConfig(
Value('username', label='Optional username', default=''), Value('username', label='Optional username', default=''),
Value('password', label='Optional password', default='', masked=True), ValueBackendPassword('password', label='Optional password', default=''),
Value('api_key', label='Optional API key', default='', masked=True), ValueBackendPassword('api_key', label='Optional API key', default='', noprompt=True),
) )
EXPIRATIONS = { EXPIRATIONS = {
@ -55,10 +55,13 @@ class PastebinBackend(BaseBackend, BasePasteBackend):
} }
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['api_key'] if self.config['api_key'] else None, username = self.config['username'].get()
self.config['username'] if self.config['username'] else None, if username:
self.config['password'] if self.config['password'] else None, password = self.config['password'].get()
get_home=False) else:
password = None
return self.create_browser(self.config['api_key'].get() if self.config['api_key'].get() else None,
username, password, get_home=False)
def new_paste(self, *args, **kwargs): def new_paste(self, *args, **kwargs):
return PastebinPaste(*args, **kwargs) return PastebinPaste(*args, **kwargs)
@ -94,7 +97,7 @@ class PastebinBackend(BaseBackend, BasePasteBackend):
else: else:
expiration = None expiration = None
with self.browser: with self.browser:
if use_api and self.config.get('api_key'): if use_api and self.config.get('api_key').get():
self.browser.api_post_paste(paste, expiration=self.EXPIRATIONS.get(expiration)) self.browser.api_post_paste(paste, expiration=self.EXPIRATIONS.get(expiration))
else: else:
self.browser.post_paste(paste, expiration=self.EXPIRATIONS.get(expiration)) self.browser.post_paste(paste, expiration=self.EXPIRATIONS.get(expiration))

View file

@ -33,10 +33,6 @@ class PiratebayBackend(BaseBackend, ICapTorrent):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'the pirate bay bittorrent tracker' DESCRIPTION = 'the pirate bay bittorrent tracker'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
#CONFIG = ValuesDict(Value('domain', label='Domain (example "ssl.what.cd")'),
# Value('protocol', label='Protocol to use', choices=('http', 'https')),
# Value('username', label='Username'),
# Value('password', label='Password', masked=True))
BROWSER = PiratebayBrowser BROWSER = PiratebayBrowser
def create_default_browser(self): def create_default_browser(self):

View file

@ -21,8 +21,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.content import ICapContent, Content from weboob.capabilities.content import ICapContent, Content
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import RedmineBrowser from .browser import RedmineBrowser
@ -37,13 +37,15 @@ class RedmineBackend(BaseBackend, ICapContent):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'The Redmine project management web application' DESCRIPTION = 'The Redmine project management web application'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('url', label='URL of the Redmine website'), CONFIG = BackendConfig(Value('url', label='URL of the Redmine website'),
Value('username', label='Login'), Value('username', label='Login'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = RedmineBrowser BROWSER = RedmineBrowser
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['url'], self.config['username'], self.config['password']) return self.create_browser(self.config['url'].get(),
self.config['username'].get(),
self.config['password'].get())
def id2path(self, id): def id2path(self, id):
return id.split('/', 2) return id.split('/', 2)

View file

@ -22,8 +22,8 @@ from __future__ import with_statement
from weboob.capabilities.messages import CantSendMessage, ICapMessages, ICapMessagesPost from weboob.capabilities.messages import CantSendMessage, ICapMessages, ICapMessagesPost
from weboob.capabilities.account import ICapAccount, StatusField from weboob.capabilities.account import ICapAccount, StatusField
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import Value, ValueBackendPassword
from .browser import SfrBrowser from .browser import SfrBrowser
@ -38,13 +38,13 @@ class SfrBackend(BaseBackend, ICapAccount, ICapMessages, ICapMessagesPost):
VERSION = '0.9' VERSION = '0.9'
DESCRIPTION = 'SFR french mobile phone provider' DESCRIPTION = 'SFR french mobile phone provider'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = ValuesDict(Value('login', label='Login'), CONFIG = BackendConfig(Value('login', label='Login'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = SfrBrowser BROWSER = SfrBrowser
ACCOUNT_REGISTER_PROPERTIES = None ACCOUNT_REGISTER_PROPERTIES = None
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['login'], self.config['password']) return self.create_browser(self.config['login'].get(), self.config['password'].get())
# ICapMessagesPost methods # ICapMessagesPost methods

View file

@ -22,8 +22,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.bank import ICapBank, AccountNotFound from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValuesDict, Value from weboob.tools.value import ValueBackendPassword, Value
from .browser import SocieteGenerale from .browser import SocieteGenerale
@ -38,13 +38,13 @@ class SocieteGeneraleBackend(BaseBackend, ICapBank):
VERSION = '0.9' VERSION = '0.9'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = u'Société Générale french bank\' website' DESCRIPTION = u'Société Générale french bank\' website'
CONFIG = ValuesDict(Value('login', label='Account ID'), CONFIG = BackendConfig(Value('login', label='Account ID'),
Value('password', label='Password', masked=True)) ValueBackendPassword('password', label='Password'))
BROWSER = SocieteGenerale BROWSER = SocieteGenerale
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(self.config['login'], return self.create_browser(self.config['login'].get(),
self.config['password']) self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts_list(): for account in self.browser.get_accounts_list():

View file

@ -73,6 +73,14 @@ class BackendsConfig(object):
continue continue
yield instance_name, backend_name, params yield instance_name, backend_name, params
def backend_exists(self, name):
"""
Return True if the backend exists in config.
"""
config = RawConfigParser()
config.read(self.confpath)
return name in config.sections()
def add_backend(self, instance_name, backend_name, params, edit=False): def add_backend(self, instance_name, backend_name, params, edit=False):
if not instance_name: if not instance_name:
raise ValueError(u'Please give a name to the configured backend.') raise ValueError(u'Please give a name to the configured backend.')

View file

@ -20,10 +20,12 @@
import os import os
from threading import RLock from threading import RLock
from copy import copy
from weboob.capabilities.base import CapBaseObject, FieldNotFound, IBaseCap, NotLoaded from weboob.capabilities.base import CapBaseObject, FieldNotFound, IBaseCap, NotLoaded
from weboob.tools.misc import iter_fields from weboob.tools.misc import iter_fields
from weboob.tools.log import getLogger from weboob.tools.log import getLogger
from weboob.tools.value import ValuesDict
__all__ = ['BaseBackend', 'ObjectNotAvailable'] __all__ = ['BaseBackend', 'ObjectNotAvailable']
@ -60,6 +62,61 @@ class BackendStorage(object):
if self.storage: if self.storage:
return self.storage.save('backends', self.name) return self.storage.save('backends', self.name)
class BackendConfig(ValuesDict):
modname = None
instname = None
weboob = None
def load(self, weboob, modname, instname, config, nofail=False):
"""
Load configuration from dict to create an instance.
@param weboob [Weboob] weboob object
@param modname [str] name of module
@param instname [str] name of instance of this backend
@param params [dict] parameters to load
@param nofail [bool] if true, this call can't fail.
@return [BackendConfig]
"""
cfg = BackendConfig()
cfg.modname = modname
cfg.instname = instname
cfg.weboob = weboob
for name, field in self.iteritems():
value = config.get(name, None)
if value is None:
if not nofail and field.required:
raise BaseBackend.ConfigError('Backend(%s): Configuration error: Missing parameter "%s" (%s)'
% (cfg.instname, name, field.description))
value = field.default
field = copy(field)
try:
field.load(cfg.instname, value, cfg.weboob.callbacks)
except ValueError, v:
if not nofail:
raise BaseBackend.ConfigError('Backend(%s): Configuration error for field "%s": %s' % (cfg.instname, name, v))
cfg[name] = field
return cfg
def dump(self):
settings = {}
for name, value in self.iteritems():
settings[name] = value.dump()
return settings
def save(self, edit=True, params=None):
assert self.modname is not None
assert self.instname is not None
assert self.weboob is not None
dump = self.dump()
if params is not None:
dump.update(params)
self.weboob.backends_config.add_backend(self.instname, self.modname, dump, edit)
class BaseBackend(object): class BaseBackend(object):
# Backend name. # Backend name.
@ -76,7 +133,7 @@ class BaseBackend(object):
LICENSE = '<unspecified>' LICENSE = '<unspecified>'
# Configuration required for this backend. # Configuration required for this backend.
# Values must be weboob.tools.value.Value objects. # Values must be weboob.tools.value.Value objects.
CONFIG = {} CONFIG = BackendConfig()
# Storage # Storage
STORAGE = {} STORAGE = {}
# Browser class # Browser class
@ -99,7 +156,7 @@ class BaseBackend(object):
def __repr__(self): def __repr__(self):
return u"<Backend '%s'>" % self.name return u"<Backend '%s'>" % self.name
def __init__(self, weboob, name, config, storage, logger=None): def __init__(self, weboob, name, config=None, storage=None, logger=None):
self.logger = getLogger(name, parent=logger) self.logger = getLogger(name, parent=logger)
self.weboob = weboob self.weboob = weboob
self.name = name self.name = name
@ -108,23 +165,9 @@ class BaseBackend(object):
# Private fields (which start with '_') # Private fields (which start with '_')
self._private_config = dict((key, value) for key, value in config.iteritems() if key.startswith('_')) self._private_config = dict((key, value) for key, value in config.iteritems() if key.startswith('_'))
# Configuration of backend # Load configuration of backend.
self.config = {} self.config = self.CONFIG.load(weboob, self.NAME, self.name, config)
for name, field in self.CONFIG.iteritems():
value = config.get(name, None)
if value is None:
if field.required:
raise BaseBackend.ConfigError('Backend(%s): Configuration error: Missing parameter "%s" (%s)' % (self.name, name, field.description))
value = field.default
try:
field.set_value(value)
except ValueError, v:
raise BaseBackend.ConfigError('Backend(%s): Configuration error for field "%s": %s' % (self.name, name, v))
# field.value is a property which converts string to right type (bool/int/float)
self.config[name] = field.value
self.storage = BackendStorage(self.name, storage) self.storage = BackendStorage(self.name, storage)
self.storage.load(self.STORAGE) self.storage.load(self.STORAGE)