save and load state of browser into storage

This commit is contained in:
Romain Bignon 2015-02-21 14:21:54 +01:00
commit cedfb5670e
4 changed files with 61 additions and 5 deletions

View file

@ -45,7 +45,9 @@ class CreditMutuelBrowser(LoginBrowser):
PROFILE = Wget() PROFILE = Wget()
BASEURL = 'https://www.creditmutuel.fr' BASEURL = 'https://www.creditmutuel.fr'
login = URL('/groupe/fr/index.html', LoginPage) login = URL('/groupe/fr/index.html',
'/(?P<subbank>.*)/fr/banques/accueil.html',
LoginPage)
login_error = URL('/(?P<subbank>.*)/fr/identification/default.cgi', LoginErrorPage) login_error = URL('/(?P<subbank>.*)/fr/identification/default.cgi', LoginErrorPage)
accounts = URL('/(?P<subbank>.*)/fr/banque/situation_financiere.cgi', AccountsPage) accounts = URL('/(?P<subbank>.*)/fr/banque/situation_financiere.cgi', AccountsPage)
user_space = URL('/(?P<subbank>.*)/fr/banque/espace_personnel.aspx', UserSpacePage) user_space = URL('/(?P<subbank>.*)/fr/banque/espace_personnel.aspx', UserSpacePage)
@ -70,6 +72,8 @@ class CreditMutuelBrowser(LoginBrowser):
currentSubBank = None currentSubBank = None
__states__ = ['currentSubBank']
def do_login(self): def do_login(self):
self.login.stay_or_go() self.login.stay_or_go()

View file

@ -320,6 +320,9 @@ class Boobank(ReplApplication):
} }
COLLECTION_OBJECTS = (Account, Transaction, ) COLLECTION_OBJECTS = (Account, Transaction, )
def load_default_backends(self):
self.load_backends(CapBank, storage=self.create_storage())
def _complete_account(self, exclude=None): def _complete_account(self, exclude=None):
if exclude: if exclude:
exclude = '%s@%s' % self.parse_id(exclude) exclude = '%s@%s' % self.parse_id(exclude)

View file

@ -20,6 +20,9 @@
from __future__ import absolute_import, print_function from __future__ import absolute_import, print_function
import re import re
import pickle
import base64
import zlib
try: try:
import urllib3 import urllib3
except ImportError: except ImportError:
@ -88,6 +91,11 @@ class Browser(object):
Maximum of threads for asynchronous requests. Maximum of threads for asynchronous requests.
""" """
__states__ = []
"""
Saved state variables.
"""
@classmethod @classmethod
def asset(cls, localfile): def asset(cls, localfile):
""" """
@ -110,7 +118,27 @@ class Browser(object):
if isinstance(self.VERIFY, basestring): if isinstance(self.VERIFY, basestring):
self.VERIFY = self.asset(self.VERIFY) self.VERIFY = self.asset(self.VERIFY)
def _save(self, response, warning=False, **kwargs): def load_state(self, state):
if 'cookies' in state:
try:
self.session.cookies = pickle.loads(zlib.decompress(base64.b64decode(state['cookies'])))
except (TypeError, zlib.error, EOFError, ValueError):
self.logger.error('Unable to reload cookies from storage')
else:
self.logger.info('Reloaded cookies from storage')
for attrname in self.__states__:
if attrname in state:
setattr(self, attrname, state[attrname])
def dump_state(self):
state = {}
state['cookies'] = base64.b64encode(zlib.compress(pickle.dumps(self.session.cookies, -1)))
for attrname in self.__states__:
state[attrname] = getattr(self, attrname)
self.logger.info('Stored cookies into storage')
return state
def save_response(self, response, warning=False, **kwargs):
if self.responses_dirname is None: if self.responses_dirname is None:
import tempfile import tempfile
self.responses_dirname = tempfile.mkdtemp(prefix='weboob_session_') self.responses_dirname = tempfile.mkdtemp(prefix='weboob_session_')
@ -194,7 +222,7 @@ class Browser(object):
profile.setup_session(session) profile.setup_session(session)
if self.logger.settings['save_responses']: if self.logger.settings['save_responses']:
session.hooks['response'].append(self._save) session.hooks['response'].append(self.save_response)
self.session = session self.session = session
@ -606,6 +634,17 @@ class PagesBrowser(DomainBrowser):
for url in self._urls.itervalues(): for url in self._urls.itervalues():
url.browser = self url.browser = self
def load_state(self, state):
super(PagesBrowser, self).load_state(state)
if 'url' in state:
self.location(state['url'])
def dump_state(self):
state = super(PagesBrowser, self).dump_state()
if self.page:
state['url'] = self.page.url
return state
def open(self, *args, **kwargs): def open(self, *args, **kwargs):
""" """
Same method than Same method than

View file

@ -285,7 +285,12 @@ class Module(object):
""" """
This abstract method is called when the backend is unloaded. This abstract method is called when the backend is unloaded.
""" """
pass if self._browser is None:
return
if hasattr(self.browser, 'dump_state'):
self.storage.set('browser_state', self.browser.dump_state())
self.storage.save()
_browser = None _browser = None
@ -346,7 +351,12 @@ class Module(object):
kwargs.setdefault('responses_dirname', os.path.join(self.logger.settings['responses_dirname'], kwargs.setdefault('responses_dirname', os.path.join(self.logger.settings['responses_dirname'],
self._private_config.get('_debug_dir', self.name))) self._private_config.get('_debug_dir', self.name)))
return self.BROWSER(*args, **kwargs) browser = self.BROWSER(*args, **kwargs)
if hasattr(browser, 'load_state'):
browser.load_state(self.storage.get('browser_state', default={}))
return browser
@classmethod @classmethod
def iter_caps(klass): def iter_caps(klass):