diff --git a/modules/carrefourbanque/browser.py b/modules/carrefourbanque/browser.py
index 4f1f95a30f33cafc4f5f2a2f0150a98b0313f17e..d2877aaf43bc040d4e69f906495744ee653e3a85 100644
--- a/modules/carrefourbanque/browser.py
+++ b/modules/carrefourbanque/browser.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see .
+# flake8: compatible
+
from __future__ import absolute_import, unicode_literals
import re
@@ -31,8 +33,8 @@
from woob.tools.compat import basestring
from .pages import (
- LoginPage, MaintenancePage, HomePage, IncapsulaResourcePage, LoanHistoryPage, CardHistoryPage, SavingHistoryPage,
- LifeInvestmentsPage, LifeHistoryPage, CardHistoryJsonPage,
+ LoginPage, MaintenancePage, HomePage, IncapsulaResourcePage, LoanHistoryPage, CardHistoryPage,
+ SavingHistoryPage, LifeInvestmentsPage, LifeHistoryPage, CardHistoryJsonPage,
)
@@ -109,7 +111,7 @@ def do_login(self):
raise RecaptchaV2Question(website_key=website_key, website_url=website_url)
else:
# we got javascript page again, this shouldn't happen
- assert False, "obfuscated javascript not managed"
+ raise AssertionError("obfuscated javascript not managed")
if self.maintenance.is_here():
raise BrowserUnavailable(self.page.get_message())
@@ -133,8 +135,8 @@ def do_login(self):
raise BrowserUnavailable(error)
elif 'saisies ne correspondent pas à l\'identifiant' in error:
raise BrowserIncorrectPassword(error)
- assert False, 'Unexpected error at login: "%s"' % error
- assert False, 'Unexpected error at login'
+ raise AssertionError('Unexpected error at login: "%s"' % error)
+ raise AssertionError('Unexpected error at login')
if self.login.is_here():
# Check if the website asks for strong authentication with OTP
@@ -191,7 +193,7 @@ def iter_history(self, account):
tr = None
total = 0
loop_limit = 500
- for page in range(loop_limit):
+ for _ in range(loop_limit):
self.card_history_json.go(data={'dateRecup': previous_date, 'index': card_index})
previous_date = self.page.get_previous_date()
diff --git a/modules/carrefourbanque/module.py b/modules/carrefourbanque/module.py
index 84535e41760e04d698ec0567f65d69b301fde575..cec8a962a3204d5319f3d909851438134615be1d 100644
--- a/modules/carrefourbanque/module.py
+++ b/modules/carrefourbanque/module.py
@@ -17,6 +17,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see .
+# flake8: compatible
+
+from __future__ import unicode_literals
from woob.capabilities.base import find_object
from woob.capabilities.bank import AccountNotFound
@@ -32,14 +35,16 @@
class CarrefourBanqueModule(Module, CapBankWealth):
NAME = 'carrefourbanque'
- MAINTAINER = u'Romain Bignon'
+ MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@weboob.org'
VERSION = '3.1'
- DESCRIPTION = u'Carrefour Banque'
+ DESCRIPTION = 'Carrefour Banque'
LICENSE = 'LGPLv3+'
- CONFIG = BackendConfig(ValueBackendPassword('login', label=u'Votre Identifiant Internet', masked=False),
- ValueBackendPassword('password', label=u"Code d'accès", regexp=u'\d+'),
- Value('captcha_response', label='Captcha Response', default='', required=False))
+ CONFIG = BackendConfig(
+ ValueBackendPassword('login', label='Votre Identifiant Internet', masked=False),
+ ValueBackendPassword('password', label="Code d'accès", regexp=r'\d+'),
+ Value('captcha_response', label='Captcha Response', default='', required=False)
+ )
BROWSER = CarrefourBanqueBrowser
def create_default_browser(self):
diff --git a/modules/carrefourbanque/pages.py b/modules/carrefourbanque/pages.py
index aad20e4407ffc4622cf6fece85560d380545e4bb..c8594c1f5be1b50aa9ac522a63f77ef596836ec0 100644
--- a/modules/carrefourbanque/pages.py
+++ b/modules/carrefourbanque/pages.py
@@ -17,12 +17,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see .
+# flake8: compatible
+
from __future__ import unicode_literals
import re
import base64
import datetime
from io import BytesIO
+
from PIL import Image
from woob.tools.json import json
@@ -51,7 +54,7 @@ class CarrefourBanqueKeyboard(object):
'6': '00011100111110111000011000001111110111111111001111100011110001111111110111110',
'7': '11111111111111000011100001100000110000110000011000011100001100001110000110000',
'8': '00111001111110110011111001111111110011110011111101100111110001111111110111110',
- '9': '00110001111110110011111000111100011111111111111110000011000011011111101111100'
+ '9': '00110001111110110011111000111100011111111111111110000011000011011111101111100',
}
def __init__(self, data_code):
@@ -160,9 +163,9 @@ def check_action_needed(self):
# The real message contains the user's phone number, so we send a generic message.
raise ActionNeeded(
"Veuillez vous connecter sur le site de Carrefour Banque pour "
- "recevoir un code par SMS afin d'accéder à votre Espace Client."
+ + "recevoir un code par SMS afin d'accéder à votre Espace Client."
)
- assert False, 'Unhandled error: password submission failed and we are still on Login Page.'
+ raise AssertionError('Unhandled error: password submission failed and we are still on Login Page.')
def get_error_message(self):
return CleanText('//div[@class="messages error"]', default=None)(self.doc)
@@ -198,14 +201,17 @@ class item_account_generic(ItemElement):
klass = Account
def obj_balance(self):
- balance = CleanDecimal('.//div[contains(@class, "right_col")]//h2[1]', replace_dots=True)(self)
+ balance = CleanDecimal.French('.//div[contains(@class, "right_col")]//h2[1]')(self)
if Field('type')(self) in (Account.TYPE_LOAN, ):
return -balance
return balance
obj_currency = Currency('.//div[contains(@class, "right_col")]//h2[1]')
obj_label = CleanText('.//div[contains(@class, "leftcol")]//h2[1]')
- obj_id = Regexp(CleanText('.//div[contains(@class, "leftcol")]//p'), ":\s+([\d]+)")
+ obj_id = Regexp(
+ CleanText('.//div[contains(@class, "leftcol")]//p'),
+ r':\s+([\d]+)'
+ )
obj_number = Field('id')
def obj_url(self):
@@ -215,13 +221,13 @@ def obj_url(self):
class iter_history_generic(Transaction.TransactionsElement):
- head_xpath = u'//div[*[contains(text(), "opérations")]]/table//thead/tr/th'
- item_xpath = u'//div[*[contains(text(), "opérations")]]/table/tbody/tr[td]'
+ head_xpath = '//div[*[contains(text(), "opérations")]]/table//thead/tr/th'
+ item_xpath = '//div[*[contains(text(), "opérations")]]/table/tbody/tr[td]'
col_debittype = 'Mode'
def next_page(self):
- next_page = Link(u'//a[contains(text(), "précédentes")]', default=None)(self)
+ next_page = Link('//a[contains(text(), "précédentes")]', default=None)(self)
if next_page:
return "/%s" % next_page
@@ -256,12 +262,11 @@ class item(item_account_generic):
obj_type = Account.TYPE_CARD
def obj_balance(self):
- available = CleanDecimal(
+ available = CleanDecimal.French(
'.//p[contains(., "encours depuis le")]//preceding-sibling::h2',
- default=None,
- replace_dots=True
+ default=NotAvailable,
)(self)
- if available is not None:
+ if available:
return -available
# No "en cours" available: return - (total_amount - available_amount)
@@ -294,10 +299,18 @@ class item(item_account_generic):
obj_url = Link('.//a[contains(., "Historique des opérations")]')
def obj_balance(self):
- val = CleanDecimal('.//a[contains(text(), "versement")]//preceding-sibling::h2', replace_dots=True, default=NotAvailable)(self)
+ val = CleanDecimal.French(
+ './/a[contains(text(), "versement")]//preceding-sibling::h2',
+ default=NotAvailable
+ )(self)
if val is not NotAvailable:
return val
- val = CleanDecimal(Regexp(CleanText('./div[@class="right_col_wrapper"]//h2'), r'([\d ,]+€)'), replace_dots=True)(self)
+ val = CleanDecimal.French(
+ Regexp(
+ CleanText('./div[@class="right_col_wrapper"]//h2'),
+ r'([\d ,]+€)'
+ ),
+ )(self)
return val
@method
@@ -309,11 +322,15 @@ class item(item_account_generic):
def obj_url(self):
acc_number = Field('id')(self)
- xpath_link = '//li[contains(., "{acc_number}")]/ul/li/a[contains(text(), "Dernieres opérations")]'.format(acc_number=acc_number)
+ xpath_link = (
+ '//li[contains(., "{acc_number}")]/ul/li/a[contains(text(), "Dernieres opérations")]'
+ ).format(acc_number=acc_number)
return Link(xpath_link)(self)
def obj__life_investments(self):
- xpath_link = '//li[contains(., "{acc_number}")]/ul/li/a[contains(text(), "Solde")]'.format(acc_number=Field('id')(self))
+ xpath_link = '//li[contains(., "{acc_number}")]/ul/li/a[contains(text(), "Solde")]'.format(
+ acc_number=Field('id')(self)
+ )
return Link(xpath_link)(self)
@@ -339,11 +356,11 @@ class get_investment(TableElement):
item_xpath = '//table[@id="assets"]/tbody/tr[position() > 1]'
head_xpath = '//table[@id="assets"]/tbody/tr[1]/td'
- col_label = u'Fonds'
- col_quantity = u'Nombre de parts'
- col_unitvalue = u'Valeur part'
- col_valuation = u'Total'
- col_portfolio_share = u'Répartition'
+ col_label = 'Fonds'
+ col_quantity = 'Nombre de parts'
+ col_unitvalue = 'Valeur part'
+ col_valuation = 'Total'
+ col_portfolio_share = 'Répartition'
class item(ItemElement):
klass = Investment
@@ -395,7 +412,11 @@ def on_load(self):
#
# this function converts the response to the good format if needed
if isinstance(self.doc['tab_historique'], dict):
- self.doc['tab_historique'] = sorted(self.doc['tab_historique'].values(), key=lambda x: x['timestampOperation'], reverse=True)
+ self.doc['tab_historique'] = sorted(
+ self.doc['tab_historique'].values(),
+ key=lambda x: x['timestampOperation'],
+ reverse=True
+ )
elif self.doc['tab_historique'] is None:
# No transaction available, set value to empty dict
@@ -410,7 +431,10 @@ class item(ItemElement):
klass = Transaction
def obj_date(self):
- return datetime.datetime.strptime(CleanText(Dict('timestampOperation'))(self), "%Y-%m-%d-%H.%M.%S.%f").date()
+ return datetime.datetime.strptime(
+ CleanText(Dict('timestampOperation'))(self),
+ "%Y-%m-%d-%H.%M.%S.%f"
+ ).date()
obj_rdate = Date(CleanText(Dict('date')), dayfirst=True)
obj_raw = CleanText(Dict('label'))