Pep8 cleanups for ING module

This commit is contained in:
Florent 2012-03-13 14:56:36 +01:00
commit a0d81b0ae1
8 changed files with 106 additions and 89 deletions

View file

@ -20,4 +20,5 @@
from .backend import INGBackend from .backend import INGBackend
__all__ = ['INGBackend'] __all__ = ['INGBackend']

View file

@ -38,9 +38,16 @@ class INGBackend(BaseBackend, ICapBank):
VERSION = '0.b' VERSION = '0.b'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
DESCRIPTION = 'ING Direct French bank website' DESCRIPTION = 'ING Direct French bank website'
CONFIG = BackendConfig(ValueBackendPassword('login', label='Account ID', masked=False), CONFIG = BackendConfig(ValueBackendPassword('login',
ValueBackendPassword('password', label='Password', regexp='^(\d{6}|)$'), label='Account ID',
ValueBackendPassword('birthday', label='Birthday', regexp='^(\d{8}|)$', masked=False) masked=False),
ValueBackendPassword('password',
label='Password',
regexp='^(\d{6}|)$'),
ValueBackendPassword('birthday',
label='Birthday',
regexp='^(\d{8}|)$',
masked=False)
) )
BROWSER = Ing BROWSER = Ing
@ -72,4 +79,3 @@ class INGBackend(BaseBackend, ICapBank):
with self.browser: with self.browser:
for coming in self.browser.get_coming_operations(account.id): for coming in self.browser.get_coming_operations(account.id):
yield coming yield coming

View file

@ -29,7 +29,7 @@ __all__ = ['Ing']
class Ing(BaseBrowser): class Ing(BaseBrowser):
DOMAIN = 'secure.ingdirect.fr' DOMAIN = 'secure.ingdirect.fr'
PROTOCOL = 'https' PROTOCOL = 'https'
ENCODING = None # refer to the HTML encoding ENCODING = None # refer to the HTML encoding
PAGES = {'.*displayTRAccountSummary.*': AccountsList, PAGES = {'.*displayTRAccountSummary.*': AccountsList,
'.*displayLogin.jsf': LoginPage, '.*displayLogin.jsf': LoginPage,
'.*displayLogin.jsf.*': LoginPage2, '.*displayLogin.jsf.*': LoginPage2,
@ -38,7 +38,7 @@ class Ing(BaseBrowser):
} }
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.birthday = kwargs.pop('birthday', None) self.birthday = kwargs.pop('birthday', None)
BaseBrowser.__init__(self, *args, **kwargs) BaseBrowser.__init__(self, *args, **kwargs)
def home(self): def home(self):
@ -55,10 +55,11 @@ class Ing(BaseBrowser):
assert self.birthday.isdigit() assert self.birthday.isdigit()
if not self.is_on_page(LoginPage): if not self.is_on_page(LoginPage):
self.location('https://secure.ingdirect.fr/public/displayLogin.jsf') self.location('https://secure.ingdirect.fr/\
public/displayLogin.jsf')
self.page.prelogin(self.username, self.birthday) self.page.prelogin(self.username, self.birthday)
self.page.login(self.password) self.page.login(self.password)
def get_accounts_list(self): def get_accounts_list(self):
if not self.is_on_page(AccountsList): if not self.is_on_page(AccountsList):
@ -83,12 +84,16 @@ class Ing(BaseBrowser):
account = self.get_account(id) account = self.get_account(id)
# The first and the second letter of the label are the account type # The first and the second letter of the label are the account type
if account.label[0:2] == "CC": if account.label[0:2] == "CC":
self.location('https://secure.ingdirect.fr/protected/pages/cc/accountDetail.jsf') self.location('https://secure.ingdirect.fr/\
protected/pages/cc/accountDetail.jsf')
elif account.label[0:2] == "LA": elif account.label[0:2] == "LA":
# we want "displayTRHistoriqueLA" but this fucking page is not directly available... # we want "displayTRHistoriqueLA" but this fucking page
self.location('https://secure.ingdirect.fr/general?command=goToAccount&account=%d&zone=COMPTE' % int(id)) # is not directly available...
self.location('https://secure.ingdirect.fr/\
general?command=goToAccount&account=%d&zone=COMPTE'\
% int(id))
else: else:
raise NotImplementedError() raise NotImplementedError()
return self.page.get_transactions() return self.page.get_transactions()
# TODO # TODO

View file

@ -22,7 +22,9 @@ from .accounts_list import AccountsList
from .account_history import AccountHistoryCC, AccountHistoryLA from .account_history import AccountHistoryCC, AccountHistoryLA
from .login import LoginPage, LoginPage2, ConfirmPage, MessagePage from .login import LoginPage, LoginPage2, ConfirmPage, MessagePage
class AccountPrelevement(AccountsList): pass
__all__ = ['AccountsList', 'AccountHistoryCC', 'AccountHistoryLA', 'LoginPage', 'LoginPage2', class AccountPrelevement(AccountsList):
'ConfirmPage', 'MessagePage', 'AccountPrelevement'] pass
__all__ = ['AccountsList', 'AccountHistoryCC', 'AccountHistoryLA', 'LoginPage',
'LoginPage2', 'ConfirmPage', 'MessagePage', 'AccountPrelevement']

View file

@ -27,11 +27,9 @@ from weboob.capabilities.base import NotAvailable
__all__ = ['AccountHistoryCC', 'AccountHistoryLA'] __all__ = ['AccountHistoryCC', 'AccountHistoryLA']
class AccountHistoryCC(BasePage): class AccountHistoryCC(BasePage):
types = { types = {
'Carte achat': Transaction.TYPE_CARD, 'Carte achat': Transaction.TYPE_CARD,
'Virement': Transaction.TYPE_TRANSFER, 'Virement': Transaction.TYPE_TRANSFER,
'Carte retrait': Transaction.TYPE_WITHDRAWAL, 'Carte retrait': Transaction.TYPE_WITHDRAWAL,
u'Prélèvement': Transaction.TYPE_ORDER, u'Prélèvement': Transaction.TYPE_ORDER,
@ -47,12 +45,13 @@ class AccountHistoryCC(BasePage):
texte = tr.text_content().split('\n') texte = tr.text_content().split('\n')
op = Transaction(id) op = Transaction(id)
op.label = texte[2] op.label = texte[2]
op.raw = texte[2] # nothing to parse op.raw = texte[2] # nothing to parse
op.date = date(*reversed([int(x) for x in texte[0].split('/')])) op.date = date(*reversed([int(x) for x in texte[0].split('/')]))
op.category = texte[4] op.category = texte[4]
op.type = self.types.get(texte[4], Transaction.TYPE_UNKNOWN) op.type = self.types.get(texte[4], Transaction.TYPE_UNKNOWN)
amount = texte[5].replace('\t','').strip().replace(u'', '').replace(',', '.').replace(u'\xa0', u'') amount = texte[5].replace('\t', '').strip().replace(u'', '').\
replace(',', '.').replace(u'\xa0', u'')
op.amount = float(amount) op.amount = float(amount)
self.transactions.append(op) self.transactions.append(op)
@ -61,6 +60,7 @@ class AccountHistoryCC(BasePage):
def get_transactions(self): def get_transactions(self):
return self.transactions return self.transactions
class AccountHistoryLA(BasePage): class AccountHistoryLA(BasePage):
def on_loaded(self): def on_loaded(self):
@ -69,23 +69,22 @@ class AccountHistoryLA(BasePage):
history = self.document.xpath('//tr[@align="center"]') history = self.document.xpath('//tr[@align="center"]')
history.pop(0) history.pop(0)
for tr in history: for tr in history:
id = i id = i
texte = tr.text_content().strip().split('\n') texte = tr.text_content().strip().split('\n')
op = Transaction(id) op = Transaction(id)
# The size is not the same if there are two dates or only one # The size is not the same if there are two dates or only one
length = len(texte) length = len(texte)
op.raw = unicode(texte[length - 2].strip()) op.raw = unicode(texte[length - 2].strip())
op.date = date(*reversed([int(x) for x in texte[0].split('/')])) op.date = date(*reversed([int(x) for x in texte[0].split('/')]))
op.category = NotAvailable op.category = NotAvailable
amount = texte[length - 1].replace('\t','').strip().replace('.', '').replace(u'', '').replace(',', '.').replace(u'\xa0', u'') amount = texte[length - 1].replace('\t', '').strip().\
op.amount = float(amount) replace('.', '').replace(u'', '').\
replace(',', '.').replace(u'\xa0', u'')
op.amount = float(amount)
self.transactions.append(op)
i += 1
self.transactions.append(op)
i += 1
def get_transactions(self): def get_transactions(self):
return self.transactions return self.transactions

View file

@ -39,15 +39,16 @@ class AccountsList(BasePage):
account = Account() account = Account()
link = td.xpath('.//a')[0] link = td.xpath('.//a')[0]
account.id = re.search('\d', link.attrib['href']).group(0) account.id = re.search('\d', link.attrib['href']).group(0)
if not ( account.id in ids ) : if not (account.id in ids):
ids.append( account.id ) ids.append(account.id)
account.label = link.text account.label = link.text
urltofind = './/a[@href="' + link.attrib['href'] + '"]' urltofind = './/a[@href="' + link.attrib['href'] + '"]'
linkbis = self.document.xpath(urltofind).pop() linkbis = self.document.xpath(urltofind).pop()
if linkbis.text == link.text : if linkbis.text == link.text:
linkbis=self.document.xpath(urltofind)[1] linkbis = self.document.xpath(urltofind)[1]
account.balance = float( linkbis.text.replace('.','').replace(' ', '').replace(',','.') ) account.balance = float(linkbis.text.replace('.', '').\
replace(' ', '').replace(',', '.'))
account.coming = NotAvailable account.coming = NotAvailable
l.append(account) l.append(account)
return l return l

View file

@ -23,33 +23,34 @@ from weboob.tools.mech import ClientForm
from logging import error from logging import error
from weboob.tools.browser import BasePage from weboob.tools.browser import BasePage
from weboob.tools.captcha.virtkeyboard import VirtKeyboard,VirtKeyboardError from weboob.tools.captcha.virtkeyboard import VirtKeyboard, VirtKeyboardError
import tempfile import tempfile
__all__ = ['LoginPage', 'LoginPage2', 'ConfirmPage', 'ChangePasswordPage'] __all__ = ['LoginPage', 'LoginPage2', 'ConfirmPage', 'ChangePasswordPage']
class INGVirtKeyboard(VirtKeyboard): class INGVirtKeyboard(VirtKeyboard):
symbols={'0':'327208d491507341908cf6920f26b586', symbols = {'0': '327208d491507341908cf6920f26b586',
'1':'615ff37b15645da106cebc4605b399de', '1': '615ff37b15645da106cebc4605b399de',
'2':'fb04e648c93620f8b187981f9742b57e', '2': 'fb04e648c93620f8b187981f9742b57e',
'3':'b786d471a70de83657d57bdedb6a2f38', '3': 'b786d471a70de83657d57bdedb6a2f38',
'4':'41b5501219e8d8f6d3b0baef3352ce88', '4': '41b5501219e8d8f6d3b0baef3352ce88',
'5':'c72b372fb035160f2ff8dae59cd7e174', '5': 'c72b372fb035160f2ff8dae59cd7e174',
'6':'392fa79e9a1749f5c8c0170f6a8ec68b', '6': '392fa79e9a1749f5c8c0170f6a8ec68b',
'7':'fb495b5cf7f46201af0b4977899b56d4', '7': 'fb495b5cf7f46201af0b4977899b56d4',
'8':'e8fea1e1aa86f8fca7f771db9a1dca4d', '8': 'e8fea1e1aa86f8fca7f771db9a1dca4d',
'9':'82e63914f2e52ec04c11cfc6fecf7e08' '9': '82e63914f2e52ec04c11cfc6fecf7e08'
} }
color=64 color = 64
def __init__(self, basepage):
def __init__(self,basepage):
divkeyboard = basepage.document.find("//div[@id='clavierdisplayLogin']") divkeyboard = basepage.document.find("//div[@id='clavierdisplayLogin']")
img = divkeyboard.xpath("img")[1] img = divkeyboard.xpath("img")[1]
if img is None: if img is None:
return False return False
url=img.attrib.get("src") url = img.attrib.get("src")
coords={} coords = {}
coords["11"] = (5, 5, 33, 33) coords["11"] = (5, 5, 33, 33)
coords["21"] = (45, 5, 73, 33) coords["21"] = (45, 5, 73, 33)
coords["31"] = (85, 5, 113, 33) coords["31"] = (85, 5, 113, 33)
@ -66,66 +67,66 @@ class INGVirtKeyboard(VirtKeyboard):
if basepage.browser.responses_dirname is None: if basepage.browser.responses_dirname is None:
basepage.browser.responses_dirname = \ basepage.browser.responses_dirname = \
tempfile.mkdtemp(prefix='weboob_session_') tempfile.mkdtemp(prefix='weboob_session_')
self.check_symbols(self.symbols,basepage.browser.responses_dirname) self.check_symbols(self.symbols, basepage.browser.responses_dirname)
def get_string_code(self,string): def get_string_code(self, string):
code='' code = ''
first = True first = True
for c in string: for c in string:
if not first: if not first:
code+="," code += ","
else : else:
first = False first = False
codesymbol = self.get_symbol_code(self.symbols[c]) codesymbol = self.get_symbol_code(self.symbols[c])
x = (self.coords[codesymbol][0] + self.coords[codesymbol][2]) / 2 # In the middle x = (self.coords[codesymbol][0] + self.coords[codesymbol][2]) / 2
y = (self.coords[codesymbol][1] + self.coords[codesymbol][3]) / 2 y = (self.coords[codesymbol][1] + self.coords[codesymbol][3]) / 2
code+=str(x) code += str(x)
code+="," code += ","
code+=str(y) code += str(y)
return code return code
class LoginPage(BasePage): class LoginPage(BasePage):
def on_loaded(self): def on_loaded(self):
pass pass
def prelogin(self, login, birthday): def prelogin(self, login, birthday):
# First step : login and birthday # First step : login and birthday
self.browser.select_form('zone1Form') self.browser.select_form('zone1Form')
self.browser.set_all_readonly(False) self.browser.set_all_readonly(False)
self.browser['zone1Form:numClient'] = login self.browser['zone1Form:numClient'] = login
self.browser['zone1Form:dateDay'] = birthday[0:2] self.browser['zone1Form:dateDay'] = birthday[0:2]
self.browser['zone1Form:dateMonth'] = birthday[2:4] self.browser['zone1Form:dateMonth'] = birthday[2:4]
self.browser['zone1Form:dateYear'] = birthday[4:9] self.browser['zone1Form:dateYear'] = birthday[4:9]
self.browser['zone1Form:radioSaveClientNumber'] = False self.browser['zone1Form:radioSaveClientNumber'] = False
self.browser.submit(nologin=True) self.browser.submit(nologin=True)
class LoginPage2(BasePage): class LoginPage2(BasePage):
def on_loaded(self): def on_loaded(self):
pass pass
def login(self, password): def login(self, password):
# 2) And now, the virtual Keyboard # 2) And now, the virtual Keyboard
try: try:
vk=INGVirtKeyboard(self) vk = INGVirtKeyboard(self)
except VirtKeyboardError,err: except VirtKeyboardError, err:
error("Error: %s"%err) error("Error: %s" % err)
return False return False
realpasswd = "" realpasswd = ""
span = self.document.find('//span[@id="digitpaddisplayLogin"]') span = self.document.find('//span[@id="digitpaddisplayLogin"]')
i = 0 i = 0
for font in span.getiterator('font'): for font in span.getiterator('font'):
if font.attrib.get('class') == "vide": if font.attrib.get('class') == "vide":
realpasswd += password[i] realpasswd += password[i]
i+=1 i += 1
self.browser.logger.debug('We are looking for : ' + realpasswd) self.browser.logger.debug('We are looking for : ' + realpasswd)
self.browser.select_form('mrc') self.browser.select_form('mrc')
self.browser.set_all_readonly(False) self.browser.set_all_readonly(False)
self.browser.logger.debug("Coordonates: "+ vk.get_string_code(realpasswd)) self.browser.logger.debug("Coordonates: " + vk.get_string_code(realpasswd))
self.browser.controls.append(ClientForm.TextControl('text', 'mrc:mrg', {'value': ''})) self.browser.controls.append(ClientForm.TextControl('text', 'mrc:mrg', {'value': ''}))
self.browser.controls.append(ClientForm.TextControl('text', 'AJAXREQUEST', {'value': ''})) self.browser.controls.append(ClientForm.TextControl('text', 'AJAXREQUEST', {'value': ''}))
self.browser['AJAXREQUEST']='_viewRoot' self.browser['AJAXREQUEST'] = '_viewRoot'
self.browser['mrc:mrldisplayLogin'] = vk.get_string_code(realpasswd) self.browser['mrc:mrldisplayLogin'] = vk.get_string_code(realpasswd)
self.browser['mrc:mrg'] = 'mrc:mrg' self.browser['mrc:mrg'] = 'mrc:mrg'
self.browser.submit(nologin=True) self.browser.submit(nologin=True)
@ -144,11 +145,12 @@ class ConfirmPage(BasePage):
if m: if m:
return m.group(1) return m.group(1)
class MessagePage(BasePage): class MessagePage(BasePage):
def on_loaded(self): def on_loaded(self):
pass pass
class ChangePasswordPage(BasePage): class ChangePasswordPage(BasePage):
def on_loaded(self): def on_loaded(self):
pass pass

View file

@ -20,6 +20,7 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
class INGTest(BackendTest): class INGTest(BackendTest):
BACKEND = 'ing' BACKEND = 'ing'