diff --git a/modules/bnporc/__init__.py b/modules/bnporc/__init__.py
index 00adecdc3240babc5bf4b5825fd8ef3b50b160cc..00c9df3bccdf6ef35dd6ecf35e024e38a44533de 100644
--- a/modules/bnporc/__init__.py
+++ b/modules/bnporc/__init__.py
@@ -17,7 +17,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
-
from .module import BNPorcModule
__all__ = ['BNPorcModule']
diff --git a/modules/bnporc/company/browser.py b/modules/bnporc/company/browser.py
index 1e1a5ff2317b247c39e2036350c48c4575f1626d..9e9f48cb7dff14f5c70cd156045977f9930ee87d 100644
--- a/modules/bnporc/company/browser.py
+++ b/modules/bnporc/company/browser.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
from datetime import date, timedelta
@@ -28,7 +30,6 @@
from .pages import LoginPage, AccountsPage, HistoryPage
-
__all__ = ['BNPCompany']
@@ -49,7 +50,6 @@ def do_login(self):
self.page.login(self.username, self.password)
-
@need_login
def iter_accounts(self):
self.accounts.go()
@@ -74,10 +74,11 @@ def get_transactions(self, id_account, typeReleve, dateMin, dateMax='null'):
@need_login
def iter_history(self, account):
- return self.get_transactions(account.id,
- 'Comptable',
- (date.today() - timedelta(days=90)).strftime('%Y%m%d'),
- date.today().strftime('%Y%m%d'))
+ return self.get_transactions(
+ account.id,
+ 'Comptable', (date.today() - timedelta(days=90)).strftime('%Y%m%d'),
+ date.today().strftime('%Y%m%d')
+ )
@need_login
def iter_documents(self, subscription):
@@ -89,9 +90,7 @@ def iter_subscription(self):
@need_login
def iter_coming_operations(self, account):
- return self.get_transactions(account.id,
- 'Previsionnel',
- (date.today().strftime('%Y%m%d')))
+ return self.get_transactions(account.id, 'Previsionnel', (date.today().strftime('%Y%m%d')))
@need_login
def iter_investment(self, account):
diff --git a/modules/bnporc/company/pages.py b/modules/bnporc/company/pages.py
index 631fbe3d4f64d04768c7faaa145efecd730d3068..97e776d01d09875d1d30ddd182909fd8ea368171 100644
--- a/modules/bnporc/company/pages.py
+++ b/modules/bnporc/company/pages.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
from io import BytesIO
@@ -32,19 +34,20 @@
class BNPVirtKeyboard(MappedVirtKeyboard):
- symbols = {'0': 'ff069462836e30a39c911034048f5bb3',
- '1': '7969f04e4e82eaefa2ce7a9a23c26178',
- '2': '1e6020f97ca1c3ce3da4f39ded15d67d',
- '3': 'f84284b40aea93c24814e23e14e76cc8',
- '4': '88bab262d4b344c0ef8f06ddd01adbcf',
- '5': '0a270764fc5d8334bcb55053432b26cb',
- '6': 'e6a4444a6c752cd3e655f2883e530080',
- '7': '933d4ca5df6b2b3df2dea00a21a3fed6',
- '8': ['f28b918777d21a5fde2bffb9899e2138', 'a97e6e27159084d50f8ef00548b70252'],
- '9': 'be751b77af0d998ab4c2cfd38455b2a6',
- }
-
- color=(0,0,0)
+ symbols = {
+ '0': 'ff069462836e30a39c911034048f5bb3',
+ '1': '7969f04e4e82eaefa2ce7a9a23c26178',
+ '2': '1e6020f97ca1c3ce3da4f39ded15d67d',
+ '3': 'f84284b40aea93c24814e23e14e76cc8',
+ '4': '88bab262d4b344c0ef8f06ddd01adbcf',
+ '5': '0a270764fc5d8334bcb55053432b26cb',
+ '6': 'e6a4444a6c752cd3e655f2883e530080',
+ '7': '933d4ca5df6b2b3df2dea00a21a3fed6',
+ '8': ['f28b918777d21a5fde2bffb9899e2138', 'a97e6e27159084d50f8ef00548b70252'],
+ '9': 'be751b77af0d998ab4c2cfd38455b2a6',
+ }
+
+ color = (0, 0, 0)
def __init__(self, basepage):
img = basepage.doc.xpath('//img[@id="gridpass_img"]')[0]
diff --git a/modules/bnporc/enterprise/browser.py b/modules/bnporc/enterprise/browser.py
index dd2602188f019563b69d4a2addab15dece63a8fc..3860d54bcf888c3bbcc79d29ed0d09ed0ddd67e8 100644
--- a/modules/bnporc/enterprise/browser.py
+++ b/modules/bnporc/enterprise/browser.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
from datetime import datetime
@@ -36,27 +38,37 @@
PasswordExpiredPage, TransactionPage, MarketPage, InvestPage,
)
-
__all__ = ['BNPEnterprise']
class BNPEnterprise(LoginBrowser):
BASEURL = 'https://secure1.entreprises.bnpparibas.net'
- login = URL('/sommaire/jsp/identification.jsp',
- '/sommaire/generateImg', LoginPage)
+ login = URL('/sommaire/jsp/identification.jsp', '/sommaire/generateImg', LoginPage)
auth = URL('/sommaire/PseMenuServlet', AuthPage)
accounts = URL('/NCCPresentationWeb/e10_soldes/liste_soldes.do', AccountsPage)
- account_history_view = URL('/NCCPresentationWeb/e10_soldes/init.do\?nccIdSelected=NCC_Soldes',
- '/NCCPresentationWeb/e11_releve_op/init.do\?identifiant=(?P)'
- '&typeSolde=(?P)&typeReleve=(?P)&typeDate=(?P)'
- '&dateMin=(?P)&dateMax=(?P)&ajax=true',
- '/NCCPresentationWeb/e11_releve_op/init.do', AccountHistoryViewPage)
- account_coming_view = URL('/NCCPresentationWeb/m04_selectionCompteGroupe/init.do\?type=compte&identifiant=(?P)', AccountHistoryViewPage)
- account_history = URL('/NCCPresentationWeb/e11_releve_op/listeOperations.do\?identifiant=(?P)&typeSolde=(?P)&typeReleve=(?P)&typeDate=(?P)&dateMin=(?P)&dateMax=(?P)&ajax=true',
- '/NCCPresentationWeb/e11_releve_op/listeOperations.do', AccountHistoryPage)
- account_coming = URL('/NCCPresentationWeb/e12_rep_cat_op/listOperations.do\?periode=date_valeur&identifiant=(?P)',
- '/NCCPresentationWeb/e12_rep_cat_op/listOperations.do', AccountHistoryPage)
+ account_history_view = URL(
+ '/NCCPresentationWeb/e10_soldes/init.do\?nccIdSelected=NCC_Soldes',
+ '/NCCPresentationWeb/e11_releve_op/init.do\?identifiant=(?P)'
+ '&typeSolde=(?P)&typeReleve=(?P)&typeDate=(?P)'
+ '&dateMin=(?P)&dateMax=(?P)&ajax=true',
+ '/NCCPresentationWeb/e11_releve_op/init.do',
+ AccountHistoryViewPage
+ )
+ account_coming_view = URL(
+ '/NCCPresentationWeb/m04_selectionCompteGroupe/init.do\?type=compte&identifiant=(?P)',
+ AccountHistoryViewPage
+ )
+ account_history = URL(
+ '/NCCPresentationWeb/e11_releve_op/listeOperations.do\?identifiant=(?P)&typeSolde=(?P)&typeReleve=(?P)&typeDate=(?P)&dateMin=(?P)&dateMax=(?P)&ajax=true',
+ '/NCCPresentationWeb/e11_releve_op/listeOperations.do',
+ AccountHistoryPage
+ )
+ account_coming = URL(
+ '/NCCPresentationWeb/e12_rep_cat_op/listOperations.do\?periode=date_valeur&identifiant=(?P)',
+ '/NCCPresentationWeb/e12_rep_cat_op/listOperations.do',
+ AccountHistoryPage
+ )
transaction_detail = URL(r'/NCCPresentationWeb/e21/getOptBDDF.do', TransactionPage)
invest = URL(r'/opcvm/lister-composition/afficher.do', InvestPage)
@@ -139,7 +151,11 @@ def _iter_history_base(self, account):
# To avoid duplicated transactions we exit as soon a transaction is not within the expected timeframe
for date in rrule(MONTHLY, dtstart=(datetime.now() - relativedelta(months=11)), until=datetime.now())[::-1]:
- params = dict(identifiant=account.iban, type_solde='C', type_releve='Previsionnel', type_date='O',
+ params = dict(
+ identifiant=account.iban,
+ type_solde='C',
+ type_releve='Previsionnel',
+ type_date='O',
date_min=(date + relativedelta(days=1) - relativedelta(months=1)).strftime(dformat),
date_max=date.strftime(dformat)
)
@@ -153,8 +169,9 @@ def _iter_history_base(self, account):
continue
if transaction.date > date:
- self.logger.debug('transaction not within expected timeframe, stop iterating history: %r',
- transaction.to_dict())
+ self.logger.debug(
+ 'transaction not within expected timeframe, stop iterating history: %r', transaction.to_dict()
+ )
return
yield transaction
diff --git a/modules/bnporc/enterprise/pages.py b/modules/bnporc/enterprise/pages.py
index b48ce343cd8e8ed27f7564940c7efdf97e783813..ecee52478e0f6c41653dc5e6e39919ef5edb4841 100644
--- a/modules/bnporc/enterprise/pages.py
+++ b/modules/bnporc/enterprise/pages.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
import re
@@ -39,22 +41,24 @@
from weboob.capabilities import NotAvailable
from weboob.exceptions import BrowserPasswordExpired, BrowserForbidden
+
def fromtimestamp(milliseconds):
- return datetime.fromtimestamp(milliseconds/1000)
+ return datetime.fromtimestamp(milliseconds / 1000)
class BNPVirtKeyboard(MappedVirtKeyboard):
- symbols = {'0': '8adee734aaefb163fb008d26bb9b3a42',
- '1': 'dad45ef18a75200030073ab102155e2f',
- '2': '6cb4c69361f5ce32b68b477db98dd0fb',
- '3': 'aa9f2d90c8112b84805d908938eefff7',
- '4': '5aa9329aceab4318c2c96130915e87b7',
- '5': 'd9fbfdf531ad888a9d79855536905d23',
- '6': '50ce19be233ac07bebb59a16a3b9d4a7',
- '7': '3a1f932237aab949fa6c59565823218b',
- '8': 'd46cf28408db75caa915edb871ea573a',
- '9': '87686fd75d283905d7651e1098db0882',
- }
+ symbols = {
+ '0': '8adee734aaefb163fb008d26bb9b3a42',
+ '1': 'dad45ef18a75200030073ab102155e2f',
+ '2': '6cb4c69361f5ce32b68b477db98dd0fb',
+ '3': 'aa9f2d90c8112b84805d908938eefff7',
+ '4': '5aa9329aceab4318c2c96130915e87b7',
+ '5': 'd9fbfdf531ad888a9d79855536905d23',
+ '6': '50ce19be233ac07bebb59a16a3b9d4a7',
+ '7': '3a1f932237aab949fa6c59565823218b',
+ '8': 'd46cf28408db75caa915edb871ea573a',
+ '9': '87686fd75d283905d7651e1098db0882',
+ }
color = (0, 0, 0)
@@ -106,8 +110,8 @@ def on_load(self):
class AccountsPage(LoggedPage, JsonPage):
TYPES = {
- 'Compte chèque': Account.TYPE_CHECKING,
- 'Compte à vue': Account.TYPE_CHECKING,
+ 'Compte chèque': Account.TYPE_CHECKING,
+ 'Compte à vue': Account.TYPE_CHECKING,
}
@method
@@ -121,9 +125,7 @@ def obj_id(self):
return CleanText(Dict('numeroCompte'))(self)[2:]
obj_balance = Eval(
- lambda x, y: x / 10**y,
- CleanDecimal(Dict('soldeComptable')),
- CleanDecimal(Dict('decSoldeComptable'))
+ lambda x, y: x / 10 ** y, CleanDecimal(Dict('soldeComptable')), CleanDecimal(Dict('decSoldeComptable'))
)
obj_label = CleanText(Dict('libelleCompte'))
obj_currency = CleanText(Dict('deviseTenue'))
@@ -133,9 +135,7 @@ def obj_type(self):
return self.page.TYPES.get(Dict('libelleType')(self), Account.TYPE_UNKNOWN)
def obj_coming(self):
- page = self.page.browser.open(
- BrowserURL('account_coming', identifiant=Field('iban'))(self)
- ).page
+ page = self.page.browser.open(BrowserURL('account_coming', identifiant=Field('iban'))(self)).page
nb_decimal = 0
if 'nb_dec' in Dict('infoOperationsAvenir/cumulTotal')(page.doc):
@@ -144,7 +144,7 @@ def obj_coming(self):
nb_decimal = Dict('infoOperationsAvenir/cumulTotal/nbDec')
coming = Eval(
- lambda x, y: x / 10**y,
+ lambda x, y: x / 10**y, # yapf: disable
CleanDecimal(Dict('infoOperationsAvenir/cumulTotal/montant', default='0')),
CleanDecimal(nb_decimal)
)(page.doc)
@@ -161,7 +161,6 @@ class get_profile(ItemElement):
class BnpHistoryItem(ItemElement):
-
def obj_raw(self):
if self.el.get('nature.libelle') and self.el.get('libelle'):
return "%s %s" % (
@@ -195,10 +194,12 @@ def load_details(self):
return
url = self.page.browser.transaction_detail.build()
- return self.page.browser.open(url, is_async=True, data={
- 'type_mvt': self.detail_type_mvt,
- 'numero_mvt': Field('_trid')(self),
- })
+ return self.page.browser.open(
+ url, is_async=True, data={
+ 'type_mvt': self.detail_type_mvt,
+ 'numero_mvt': Field('_trid')(self),
+ }
+ )
class AccountHistoryPage(LoggedPage, JsonPage):
@@ -257,10 +258,10 @@ def obj_raw(self):
def obj_type(self):
type = self.page.TYPES.get(Dict('nature/codefamille')(self), Transaction.TYPE_UNKNOWN)
- if (
- (type == Transaction.TYPE_CARD and re.search(r' RELEVE DU \d+\.', Field('raw')(self))) or
- (type == Transaction.TYPE_UNKNOWN and re.search(r'FACTURE CARTE AFFAIRES \w{16} SUIVANT RELEVE DU \d{2}.\d{2}.\d{4}', Field('raw')(self)))
- ):
+ if ((type == Transaction.TYPE_CARD and re.search(r' RELEVE DU \d+\.', Field('raw')(self))) or (
+ type == Transaction.TYPE_UNKNOWN and
+ re.search(r'FACTURE CARTE AFFAIRES \w{16} SUIVANT RELEVE DU \d{2}.\d{2}.\d{4}', Field('raw')(self))
+ )):
return Transaction.TYPE_CARD_SUMMARY
return type
@@ -289,14 +290,9 @@ def obj_vdate(self):
return fromtimestamp(Dict('dateValeur')(self))
def obj_amount(self):
- decimal_nb = Dict('montant/nbDec', default=None)(self)\
- or Dict('montant/nb_dec')(self)
+ decimal_nb = (Dict('montant/nbDec', default=None)(self) or Dict('montant/nb_dec')(self))
- return Eval(
- lambda x, y: x / 10**y,
- CleanDecimal(Dict('montant/montant')),
- decimal_nb
- )(self)
+ return Eval(lambda x, y: x / 10 ** y, CleanDecimal(Dict('montant/montant')), decimal_nb)(self)
obj__trid = Dict('id')
@@ -328,11 +324,7 @@ def obj_amount(self):
decimal_nb = Dict('montantMvmt/nbDec', default=None)(self)\
or Dict('montantMvmt/nb_dec')(self)
- return Eval(
- lambda x, y: x / 10**y,
- CleanDecimal(Dict('montantMvmt/montant')),
- decimal_nb
- )(self)
+ return Eval(lambda x, y: x / 10 ** y, CleanDecimal(Dict('montantMvmt/montant')), decimal_nb)(self)
obj__trid = Dict('idMouvement')
@@ -343,14 +335,16 @@ class TransactionPage(LoggedPage, JsonPage):
class MarketPage(LoggedPage, HTMLPage):
TYPES = {
- 'comptes de titres': Account.TYPE_MARKET,
+ 'comptes de titres': Account.TYPE_MARKET,
}
@method
class iter_market_accounts(TableElement):
def condition(self):
- return not self.el.xpath('//table[@id="table-portefeuille"]//tr/td[contains(text(), "Aucun portefeuille à afficher") \
- or contains(text(), "No portfolio to display")]')
+ return not self.el.xpath(
+ '//table[@id="table-portefeuille"]//tr/td[contains(text(), "Aucun portefeuille à afficher") \
+ or contains(text(), "No portfolio to display")]'
+ )
item_xpath = '//table[@id="table-portefeuille"]/tbody[@class="main-content"]/tr'
head_xpath = '//table[@id="table-portefeuille"]/thead/tr/th/label'
@@ -384,7 +378,9 @@ def get_token(self):
def get_id(self, label):
id_simple = re.search(r'[0-9]+', label).group(0)
- for options in self.doc.xpath('//div[@class="filterbox-content hide"]//select[@id="numero-compte-titre"]//option'):
+ for options in self.doc.xpath(
+ '//div[@class="filterbox-content hide"]//select[@id="numero-compte-titre"]//option'
+ ):
if id_simple in CleanText(options)(self.doc):
return CleanText(options.xpath('./@value'))(self)
@@ -404,7 +400,6 @@ class get_unique_market_account(ItemElement):
obj__parent = CleanText('//h3/span[span[@class="info-cheque"]]', children=False)
obj__unique = True
-
@method
class iter_investment(TableElement):
item_xpath = '//table[@class="csv-data-container hide"]//tr'
@@ -416,13 +411,11 @@ class iter_investment(TableElement):
col_unitvalue = 'Valeur de la part'
col_valuation = 'Valorisation'
col_diff = '+/- value'
-
"""
Note: Pagination is not handled yet for investments, if we find a
customer with more than 10 invests we might have to handle clicking
on the button to get 50 invests per page or check if there is a link.
"""
-
class item(ItemElement):
klass = Investment
@@ -432,7 +425,11 @@ class item(ItemElement):
obj_unitvalue = CleanDecimal(TableCell('unitvalue'), replace_dots=True)
obj_valuation = CleanDecimal(TableCell('valuation'), replace_dots=True)
obj_diff = CleanDecimal(TableCell('diff'), replace_dots=True)
- obj_code_type = lambda self: Investment.CODE_TYPE_ISIN if Field('code')(self) is not NotAvailable else NotAvailable
+
+ def obj_code_type(self):
+ if Field('code')(self):
+ return Investment.CODE_TYPE_ISIN
+ return NotAvailable
def obj_code(self):
string = CleanText(TableCell('label'))(self)
diff --git a/modules/bnporc/module.py b/modules/bnporc/module.py
index e3c0cd431f91b1bcad7808ea09a79f83d4f012a0..1cad2e55201f7ea7cc43c17be4c5b654d98f92a7 100644
--- a/modules/bnporc/module.py
+++ b/modules/bnporc/module.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
import re
@@ -42,11 +44,12 @@
from .company.browser import BNPCompany
from .pp.browser import BNPPartPro, HelloBank
-
__all__ = ['BNPorcModule']
-class BNPorcModule(Module, CapBankWealth, CapBankTransferAddRecipient, CapMessages, CapContact, CapProfile, CapDocument):
+class BNPorcModule(
+ Module, CapBankWealth, CapBankTransferAddRecipient, CapMessages, CapContact, CapProfile, CapDocument
+):
NAME = 'bnporc'
MAINTAINER = u'Romain Bignon'
EMAIL = 'romain@weboob.org'
@@ -54,15 +57,22 @@ class BNPorcModule(Module, CapBankWealth, CapBankTransferAddRecipient, CapMessag
LICENSE = 'LGPLv3+'
DESCRIPTION = 'BNP Paribas'
CONFIG = BackendConfig(
- ValueBackendPassword('login', label=u'Numéro client', masked=False),
- ValueBackendPassword('password', label=u'Code secret', regexp='^(\d{6})$'),
- ValueBool('rotating_password', label=u'Automatically renew password every 100 connections', default=False),
- ValueBool('digital_key', label=u'User with digital key have to add recipient with digital key', default=False),
- Value('website', label='Type de compte', default='pp',
- choices={'pp': 'Particuliers/Professionnels',
- 'hbank': 'HelloBank',
- 'ent': 'Entreprises',
- 'ent2': 'Entreprises et PME (nouveau site)'}))
+ ValueBackendPassword('login', label=u'Numéro client', masked=False),
+ ValueBackendPassword('password', label=u'Code secret', regexp='^(\d{6})$'),
+ ValueBool('rotating_password', label=u'Automatically renew password every 100 connections', default=False),
+ ValueBool('digital_key', label=u'User with digital key have to add recipient with digital key', default=False),
+ Value(
+ 'website',
+ label='Type de compte',
+ default='pp',
+ choices={
+ 'pp': 'Particuliers/Professionnels',
+ 'hbank': 'HelloBank',
+ 'ent': 'Entreprises',
+ 'ent2': 'Entreprises et PME (nouveau site)'
+ }
+ )
+ )
STORAGE = {'seen': []}
accepted_document_types = (
@@ -141,7 +151,9 @@ def init_transfer(self, transfer, **params):
recipient = strict_find_object(self.iter_transfer_recipients(account.id), iban=transfer.recipient_iban)
if not recipient:
- recipient = strict_find_object(self.iter_transfer_recipients(account.id), id=transfer.recipient_id, error=RecipientNotFound)
+ recipient = strict_find_object(
+ self.iter_transfer_recipients(account.id), id=transfer.recipient_id, error=RecipientNotFound
+ )
assert account.id.isdigit()
# quantize to show 2 decimals.
diff --git a/modules/bnporc/pp/browser.py b/modules/bnporc/pp/browser.py
index 6f6eaab5e7b631ce727d68990780e5bd9a1a4a08..8f2e257b9027ec5e1d9cbc43bddce07ae58e5212 100644
--- a/modules/bnporc/pp/browser.py
+++ b/modules/bnporc/pp/browser.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
from datetime import datetime
@@ -34,7 +36,6 @@
from weboob.capabilities.profile import ProfileMissing
from weboob.tools.decorators import retry
from weboob.tools.capabilities.bank.transactions import sorted_transactions
-from weboob.tools.json import json
from weboob.browser.exceptions import ServerError
from weboob.browser.elements import DataError
from weboob.exceptions import BrowserIncorrectPassword, BrowserUnavailable
@@ -56,47 +57,35 @@
__all__ = ['BNPPartPro', 'HelloBank']
-def JSON(data):
- return ('json', data)
-
-
-def isJSON(obj):
- return type(obj) is tuple and obj and obj[0] == 'json'
-
-
-class JsonBrowserMixin(object):
- def open(self, *args, **kwargs):
- if isJSON(kwargs.get('data')):
- kwargs['data'] = json.dumps(kwargs['data'][1])
- if 'headers' not in kwargs:
- kwargs['headers'] = {}
- kwargs['headers']['Content-Type'] = 'application/json'
-
- return super(JsonBrowserMixin, self).open(*args, **kwargs)
-
-
-class BNPParibasBrowser(JsonBrowserMixin, LoginBrowser, StatesMixin):
+class BNPParibasBrowser(LoginBrowser, StatesMixin):
TIMEOUT = 30.0
- login = URL(r'identification-wspl-pres/identification\?acceptRedirection=true×tamp=(?P\d+)',
- r'SEEA-pa01/devServer/seeaserver',
- r'https://mabanqueprivee.bnpparibas.net/fr/espace-prive/comptes-et-contrats\?u=%2FSEEA-pa01%2FdevServer%2Fseeaserver',
- LoginPage)
+ login = URL(
+ r'identification-wspl-pres/identification\?acceptRedirection=true×tamp=(?P\d+)',
+ r'SEEA-pa01/devServer/seeaserver',
+ r'https://mabanqueprivee.bnpparibas.net/fr/espace-prive/comptes-et-contrats\?u=%2FSEEA-pa01%2FdevServer%2Fseeaserver',
+ LoginPage
+ )
- list_error_page = URL(r'https://mabanque.bnpparibas/rsc/contrib/document/properties/identification-fr-part-V1.json', ListErrorPage)
+ list_error_page = URL(
+ r'https://mabanque.bnpparibas/rsc/contrib/document/properties/identification-fr-part-V1.json', ListErrorPage
+ )
useless_page = URL(r'/fr/connexion/comptes-et-contrats', UselessPage)
- con_threshold = URL(r'/fr/connexion/100-connexions',
- r'/fr/connexion/mot-de-passe-expire',
- r'/fr/espace-prive/100-connexions.*',
- r'/fr/espace-pro/100-connexions-pro.*',
- r'/fr/espace-pro/changer-son-mot-de-passe',
- r'/fr/espace-client/100-connexions',
- r'/fr/espace-prive/mot-de-passe-expire',
- r'/fr/client/mdp-expire',
- r'/fr/client/100-connexion',
- r'/fr/systeme/page-indisponible', ConnectionThresholdPage)
+ con_threshold = URL(
+ r'/fr/connexion/100-connexions',
+ r'/fr/connexion/mot-de-passe-expire',
+ r'/fr/espace-prive/100-connexions.*',
+ r'/fr/espace-pro/100-connexions-pro.*',
+ r'/fr/espace-pro/changer-son-mot-de-passe',
+ r'/fr/espace-client/100-connexions',
+ r'/fr/espace-prive/mot-de-passe-expire',
+ r'/fr/client/mdp-expire',
+ r'/fr/client/100-connexion',
+ r'/fr/systeme/page-indisponible',
+ ConnectionThresholdPage
+ )
accounts = URL(r'udc-wspl/rest/getlstcpt', AccountsPage)
loan_details = URL(r'caraccomptes-wspl/rpc/(?P.*)', LoanDetailsPage)
ibans = URL(r'rib-wspl/rpc/comptes', AccountsIBANPage)
@@ -109,7 +98,9 @@ class BNPParibasBrowser(JsonBrowserMixin, LoginBrowser, StatesMixin):
lifeinsurances_detail = URL(r'mefav-wspl/rest/detailMouvement', LifeInsurancesDetailPage)
natio_vie_pro = URL(r'/mefav-wspl/rest/natioViePro', NatioVieProPage)
- capitalisation_page = URL(r'https://www.clients.assurance-vie.fr/servlets/helios.cinrj.htmlnav.runtime.FrontServlet', CapitalisationPage)
+ capitalisation_page = URL(
+ r'https://www.clients.assurance-vie.fr/servlets/helios.cinrj.htmlnav.runtime.FrontServlet', CapitalisationPage
+ )
market_list = URL(r'pe-war/rpc/SAVaccountDetails/get', MarketListPage)
market_syn = URL(r'pe-war/rpc/synthesis/get', MarketSynPage)
@@ -184,7 +175,7 @@ def change_pass(self, oldpass, newpass):
@need_login
def get_profile(self):
- self.profile.go(data=JSON({}))
+ self.profile.go(json={}, method='POST')
profile = self.page.get_profile()
if profile:
return profile
@@ -192,13 +183,9 @@ def get_profile(self):
def is_loan(self, account):
return account.type in (
- Account.TYPE_LOAN,
- Account.TYPE_MORTGAGE,
- Account.TYPE_CONSUMER_CREDIT,
- Account.TYPE_REVOLVING_CREDIT
+ Account.TYPE_LOAN, Account.TYPE_MORTGAGE, Account.TYPE_CONSUMER_CREDIT, Account.TYPE_REVOLVING_CREDIT
)
-
@need_login
def iter_accounts(self):
if self.accounts_list is None:
@@ -208,12 +195,12 @@ def iter_accounts(self):
ibans = self.page.get_ibans_dict() if self.ibans.is_here() else self.ibans.go().get_ibans_dict()
# This page might be unavailable.
try:
- ibans.update(self.transfer_init.go(data=JSON({'modeBeneficiaire': '0'})).get_ibans_dict('Crediteur'))
+ ibans.update(self.transfer_init.go(json={'modeBeneficiaire': '0'}).get_ibans_dict('Crediteur'))
except (TransferAssertionError, AttributeError):
pass
accounts = list(self.accounts.go().iter_accounts(ibans=ibans))
- self.market_syn.go(data=JSON({})) # do a post on the given URL
+ self.market_syn.go(json={}, method='POST') # do a post on the given URL
market_accounts = self.page.get_list() # get the list of 'Comptes Titres'
checked_accounts = set()
for account in accounts:
@@ -282,30 +269,32 @@ def iter_history(self, account, coming=False):
return self.iter_lifeinsurance_history(account, coming)
elif account.type in (account.TYPE_MARKET, Account.TYPE_PEA) and not coming:
try:
- self.market_list.go(data=JSON({}))
+ self.market_list.go(json={}, method='POST')
except ServerError:
self.logger.warning("An Internal Server Error occurred")
return iter([])
for market_acc in self.page.get_list():
if account.number[-4:] == market_acc['securityAccountNumber'][-4:]:
- self.page = self.market_history.go(data=JSON({
- "securityAccountNumber": market_acc['securityAccountNumber'],
- }))
+ self.page = self.market_history.go(
+ json={
+ "securityAccountNumber": market_acc['securityAccountNumber'],
+ }
+ )
return self.page.iter_history()
return iter([])
else:
if not self.card_to_transaction_type:
self.list_detail_card.go()
self.card_to_transaction_type = self.page.get_card_to_transaction_type()
- data = JSON({
+ data = {
"ibanCrypte": account.id,
"pastOrPending": 1,
"triAV": 0,
"startDate": (datetime.now() - relativedelta(years=1)).strftime('%d%m%Y'),
"endDate": datetime.now().strftime('%d%m%Y')
- })
+ }
try:
- self.history.go(data=data)
+ self.history.go(json=data)
except BrowserUnavailable:
# old url is still used for certain connections bu we don't know which one is,
# so the same HistoryPage is attained by the old url in another URL object
@@ -320,17 +309,19 @@ def iter_history(self, account, coming=False):
@need_login
def iter_lifeinsurance_history(self, account, coming=False):
- self.lifeinsurances_history.go(data=JSON({
+ self.lifeinsurances_history.go(json={
"ibanCrypte": account.id,
- }))
+ })
for tr in self.page.iter_history(coming):
- page = self.lifeinsurances_detail.go(data=JSON({
- "ibanCrypte": account.id,
- "idMouvement": tr._op.get('idMouvement'),
- "ordreMouvement": tr._op.get('ordreMouvement'),
- "codeTypeMouvement": tr._op.get('codeTypeMouvement'),
- }))
+ page = self.lifeinsurances_detail.go(
+ json={
+ "ibanCrypte": account.id,
+ "idMouvement": tr._op.get('idMouvement'),
+ "ordreMouvement": tr._op.get('ordreMouvement'),
+ "codeTypeMouvement": tr._op.get('codeTypeMouvement'),
+ }
+ )
tr.investments = list(page.iter_investments())
yield tr
@@ -357,14 +348,14 @@ def iter_investment(self, account):
else:
# No capitalisation contract has yet been found in the API:
assert account.type != account.TYPE_CAPITALISATION
- self.lifeinsurances.go(data=JSON({
+ self.lifeinsurances.go(json={
"ibanCrypte": account.id,
- }))
+ })
return self.page.iter_investments()
elif account.type in (account.TYPE_MARKET, account.TYPE_PEA):
try:
- self.market_list.go(data=JSON({}))
+ self.market_list.go(json={}, method='POST')
except ServerError:
self.logger.warning("An Internal Server Error occurred")
return iter([])
@@ -372,9 +363,9 @@ def iter_investment(self, account):
if account.number[-4:] == market_acc['securityAccountNumber'][-4:] and not account.iban:
# Sometimes generate an Internal Server Error ...
try:
- self.market.go(data=JSON({
+ self.market.go(json={
"securityAccountNumber": market_acc['securityAccountNumber'],
- }))
+ })
except ServerError:
self.logger.warning("An Internal Server Error occurred")
break
@@ -385,7 +376,11 @@ def iter_investment(self, account):
@need_login
def iter_recipients(self, origin_account_id):
try:
- if not origin_account_id in self.transfer_init.go(data=JSON({'modeBeneficiaire': '0'})).get_ibans_dict('Debiteur'):
+ if (
+ not origin_account_id in self.transfer_init.go(json={
+ 'modeBeneficiaire': '0'
+ }).get_ibans_dict('Debiteur')
+ ):
raise NotImplementedError()
except TransferAssertionError:
return
@@ -398,7 +393,7 @@ def iter_recipients(self, origin_account_id):
yield recipient
if self.page.can_transfer_to_recipients(origin_account_id):
- for recipient in self.recipients.go(data=JSON({'type': 'TOUS'})).iter_recipients():
+ for recipient in self.recipients.go(json={'type': 'TOUS'}).iter_recipients():
if recipient.iban not in seen:
seen.add(recipient.iban)
yield recipient
@@ -425,7 +420,7 @@ def new_recipient(self, recipient, **params):
# need to be on recipient page send sms or mobile notification
# needed to get the phone number, enabling the possibility to send sms.
# all users with validated phone number can receive sms code
- self.recipients.go(data=JSON({'type': 'TOUS'}))
+ self.recipients.go(json={'type': 'TOUS'})
# check type of recipient activation
type_activation = 'sms'
@@ -439,10 +434,7 @@ def new_recipient(self, recipient, **params):
if type_activation == 'sms':
# post recipient data sending sms with same request
data['typeEnvoi'] = 'SMS'
- recipient = self.add_recip.go(
- data=json.dumps(data),
- headers={'Content-Type': 'application/json'}
- ).get_recipient(recipient)
+ recipient = self.add_recip.go(json=data).get_recipient(recipient)
self.rcpt_transfer_id = recipient._transfer_id
self.need_reload_state = True
raise AddRecipientStep(recipient, Value('code', label='Saisissez le code reçu par SMS.'))
@@ -451,7 +443,11 @@ def new_recipient(self, recipient, **params):
recipient.enabled_date = datetime.today()
raise AddRecipientStep(
recipient,
- ValueBool('digital_key', label='Validez pour recevoir une demande sur votre application bancaire. La validation de votre bénéficiaire peut prendre plusieurs minutes.')
+ ValueBool(
+ 'digital_key',
+ label=
+ 'Validez pour recevoir une demande sur votre application bancaire. La validation de votre bénéficiaire peut prendre plusieurs minutes.'
+ )
)
@need_login
@@ -464,7 +460,7 @@ def send_code(self, recipient, **params):
data['typeActivation'] = 1
data['codeActivation'] = params['code']
self.rcpt_transfer_id = None
- return self.activate_recip_sms.go(data=json.dumps(data), headers={'Content-Type': 'application/json'}).get_recipient(recipient)
+ return self.activate_recip_sms.go(json=data).get_recipient(recipient)
@need_login
def new_recipient_digital_key(self, recipient, data):
@@ -473,7 +469,7 @@ def new_recipient_digital_key(self, recipient, data):
"""
# post recipient data, sending app notification with same request
data['typeEnvoi'] = 'AF'
- self.add_recip.go(data=json.dumps(data), headers={'Content-Type': 'application/json'})
+ self.add_recip.go(json=data)
recipient = self.page.get_recipient(recipient)
# prepare data for polling
@@ -483,15 +479,12 @@ def new_recipient_digital_key(self, recipient, data):
polling_data['idTransaction'] = recipient._id_transaction
polling_data['typeActivation'] = 2
- timeout = time.time() + 300.00 # float(second), like bnp website
+ timeout = time.time() + 300.00 # float(second), like bnp website
# polling
while time.time() < timeout:
- time.sleep(5) # like website
- self.activate_recip_digital_key.go(
- data = json.dumps(polling_data),
- headers = {'Content-Type': 'application/json'}
- )
+ time.sleep(5) # like website
+ self.activate_recip_digital_key.go(json=polling_data)
if self.page.is_recipient_validated():
break
else:
@@ -520,11 +513,11 @@ def init_transfer(self, account, recipient, amount, reason, exec_date):
raise TransferInvalidRecipient(message="Le bénéficiaire sélectionné n'est pas activé")
data = self.prepare_transfer(account, recipient, amount, reason, exec_date)
- return self.validate_transfer.go(data=JSON(data)).handle_response(account, recipient, amount, reason)
+ return self.validate_transfer.go(json=data).handle_response(account, recipient, amount, reason)
@need_login
def execute_transfer(self, transfer):
- self.register_transfer.go(data=JSON({'referenceVirement': transfer.id}))
+ self.register_transfer.go(json={'referenceVirement': transfer.id})
return self.page.handle_response(transfer)
@need_login
@@ -575,7 +568,9 @@ def iter_documents(self, subscription):
data['ikpiPersonne'] = subscription._iduser
self.document_research.go(json=data)
- for doc in self.page.iter_documents(sub_id=subscription.id, sub_number=subscription._number, baseurl=self.BASEURL):
+ for doc in self.page.iter_documents(
+ sub_id=subscription.id, sub_number=subscription._number, baseurl=self.BASEURL
+ ):
if doc.id not in id_docs:
yield doc
diff --git a/modules/bnporc/pp/document_pages.py b/modules/bnporc/pp/document_pages.py
index e4a02e7ff11c4002db83c9d0d910ceb8db394ecf..35517ebcc1e29dce8ecc65aa3df5f45efa8e696d 100644
--- a/modules/bnporc/pp/document_pages.py
+++ b/modules/bnporc/pp/document_pages.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
import re
@@ -73,13 +75,15 @@ def condition(self):
def obj_label(self):
if 'ibanCrypte' in self.el:
- return '%s %s N° %s' % (Dict('dateDoc')(self), Dict('libelleSousFamille')(self), Dict('numeroCompteAnonymise')(self))
+ return '%s %s N° %s' % (
+ Dict('dateDoc')(self), Dict('libelleSousFamille')(self), Dict('numeroCompteAnonymise')(self)
+ )
else:
return '%s %s N° %s' % (Dict('dateDoc')(self), Dict('libelleSousFamille')(self), Dict('idContrat')(self))
def obj_url(self):
keys_to_copy = {
- 'idDocument' :'idDoc',
+ 'idDocument': 'idDoc',
'dateDocument': 'dateDoc',
'idLocalisation': 'idLocalisation',
'viDocDocument': 'viDocDocument',
diff --git a/modules/bnporc/pp/pages.py b/modules/bnporc/pp/pages.py
index 882e6dcc37622810e7cddb4c32a38e47130c8ba1..1b39f69f963f03b2b299ca613b5d90f60d742d43 100644
--- a/modules/bnporc/pp/pages.py
+++ b/modules/bnporc/pp/pages.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
+# yapf-compatible
+
from __future__ import unicode_literals
from collections import Counter
@@ -60,7 +62,6 @@ class TransferAssertionError(Exception):
class ConnectionThresholdPage(HTMLPage):
NOT_REUSABLE_PASSWORDS_COUNT = 3
"""BNP disallows to reuse one of the three last used passwords."""
-
def make_date(self, yy, m, d):
current = datetime.now().year
if yy > current - 2000:
@@ -109,8 +110,10 @@ def looks_legit(self, password):
def on_load(self):
msg = (
- CleanText('//div[@class="confirmation"]//span[span]')(self.doc) or
- CleanText('//p[contains(text(), "Vous avez atteint la date de fin de vie de votre code secret")]')(self.doc)
+ CleanText('//div[@class="confirmation"]//span[span]')(self.doc)
+ or CleanText('//p[contains(text(), "Vous avez atteint la date de fin de vie de votre code secret")]')(
+ self.doc
+ )
)
self.logger.warning('Password expired.')
@@ -154,16 +157,18 @@ def cast(x, typ, default=None):
class BNPKeyboard(GridVirtKeyboard):
color = (0x1f, 0x27, 0x28)
margin = 3, 3
- symbols = {'0': '43b2227b92e0546d742a1f087015e487',
- '1': '2914e8cc694de26756096d0d0d4c6e0f',
- '2': 'aac54304a7bb850805d29f54557be366',
- '3': '0376d9f8419efee42e253d195a152547',
- '4': '3719595f15b1ac1c5a73d84aa290b5f6',
- '5': '617597f07a6530479927536671485439',
- '6': '4f5dce7bd0d9213fdae54b79bb8dd33a',
- '7': '49e07fa52b9bcee798f3a663f86e6cc1',
- '8': 'c60b723b3d95a46416b34c2cbefba3ed',
- '9': 'a13b8c3617a7bf854590833ddfb97f1f'}
+ symbols = {
+ '0': '43b2227b92e0546d742a1f087015e487',
+ '1': '2914e8cc694de26756096d0d0d4c6e0f',
+ '2': 'aac54304a7bb850805d29f54557be366',
+ '3': '0376d9f8419efee42e253d195a152547',
+ '4': '3719595f15b1ac1c5a73d84aa290b5f6',
+ '5': '617597f07a6530479927536671485439',
+ '6': '4f5dce7bd0d9213fdae54b79bb8dd33a',
+ '7': '49e07fa52b9bcee798f3a663f86e6cc1',
+ '8': 'c60b723b3d95a46416b34c2cbefba3ed',
+ '9': 'a13b8c3617a7bf854590833ddfb97f1f'
+ }
def __init__(self, browser, image):
symbols = list('%02d' % x for x in range(1, 11))
@@ -191,7 +196,7 @@ def render_template(tmpl, **values):
@staticmethod
def generate_token(length=11):
chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'
- return ''.join((chars[randint(0, len(chars)-1)] for _ in range(length)))
+ return ''.join((chars[randint(0, len(chars) - 1)] for _ in range(length)))
def build_doc(self, text):
try:
@@ -222,7 +227,7 @@ def on_load(self):
websiteUnavailable_codes = [207, 1000, 1001]
if error in wrongpass_codes:
raise BrowserIncorrectPassword(msg)
- elif error == 21: # "Ce service est momentanément indisponible. Veuillez renouveler votre demande ultérieurement." -> In reality, account is blocked because of too much wrongpass
+ elif error == 21: # "Ce service est momentanément indisponible. Veuillez renouveler votre demande ultérieurement." -> In reality, account is blocked because of too much wrongpass
raise ActionNeeded(u"Compte bloqué")
elif error in actionNeeded_codes:
raise ActionNeeded(msg)
@@ -244,10 +249,12 @@ def login(self, username, password):
target = self.browser.BASEURL + 'SEEA-pa01/devServer/seeaserver'
user_agent = self.browser.session.headers.get('User-Agent') or ''
- auth = self.render_template(self.get('data.authTemplate'),
- idTelematique=username,
- password=vk.get_string_code(password),
- clientele=user_agent)
+ auth = self.render_template(
+ self.get('data.authTemplate'),
+ idTelematique=username,
+ password=vk.get_string_code(password),
+ clientele=user_agent
+ )
# XXX useless?
csrf = self.generate_token()
@@ -292,8 +299,12 @@ def condition(self):
klass = Person
def parse(self, el):
- if not Dict(self.item_path + 'etatCivil/prenom')(el).strip() and not Dict(self.item_path + 'etatCivil/nom')(el).strip():
+ if (
+ not Dict(self.item_path + 'etatCivil/prenom')(el).strip()
+ and not Dict(self.item_path + 'etatCivil/nom')(el).strip()
+ ):
raise ProfileMissing()
+
obj_name = Format('%s %s', Dict(item_path + 'etatCivil/prenom'), Dict(item_path + 'etatCivil/nom'))
obj_spouse_name = Dict(item_path + 'etatCivil/nomMarital', default=NotAvailable)
obj_birth_date = Date(Dict(item_path + 'etatCivil/dateNaissance'), dayfirst=True)
@@ -446,10 +457,15 @@ def on_load(self):
raise TransferAssertionError('%s, code=%s' % (message_code[0], message_code[1]))
def get_ibans_dict(self, account_type):
- return dict([(a['ibanCrypte'], a['iban']) for a in self.path('data.infoVirement.listeComptes%s.*' % account_type)])
+ return dict([(a['ibanCrypte'], a['iban'])
+ for a in self.path('data.infoVirement.listeComptes%s.*' % account_type)])
def can_transfer_to_recipients(self, origin_account_id):
- return next(a['eligibleVersBenef'] for a in self.path('data.infoVirement.listeComptesDebiteur.*') if a['ibanCrypte'] == origin_account_id) == '1'
+ return next(
+ a['eligibleVersBenef']
+ for a in self.path('data.infoVirement.listeComptesDebiteur.*')
+ if a['ibanCrypte'] == origin_account_id
+ ) == '1'
@method
class transferable_on(DictElement):
@@ -492,10 +508,15 @@ def obj_bank_name(self):
return Dict('nomBanque')(self) or NotAvailable
def obj_enabled_at(self):
- return datetime.now().replace(microsecond=0) if Dict('libelleStatut')(self) == u'Activé' else (datetime.now() + timedelta(days=5)).replace(microsecond=0)
+ if Dict('libelleStatut')(self) == u'Activé':
+ return datetime.now().replace(microsecond=0)
+ return (datetime.now() + timedelta(days=5)).replace(microsecond=0)
def has_digital_key(self):
- return Dict('data/infoBeneficiaire/authentForte')(self.doc) and Dict('data/infoBeneficiaire/nomDeviceAF', default=False)(self.doc)
+ return (
+ Dict('data/infoBeneficiaire/authentForte')(self.doc)
+ and Dict('data/infoBeneficiaire/nomDeviceAF', default=False)(self.doc)
+ )
class ValidateTransferPage(BNPPage):
@@ -566,27 +587,45 @@ def handle_response(self, transfer):
class Transaction(FrenchTransaction):
- PATTERNS = [(re.compile(u'^(?PCHEQUE)(?P.*)'), FrenchTransaction.TYPE_CHECK),
- (re.compile('^(?PFACTURE CARTE) DU (?P\d{2})(?P\d{2})(?P\d{2}) (?P.*?)( CA?R?T?E? ?\d*X*\d*)?$'),
- FrenchTransaction.TYPE_CARD),
- (re.compile('^(?P(PRELEVEMENT|TELEREGLEMENT|TIP)) (?P.*)'),
- FrenchTransaction.TYPE_ORDER),
- (re.compile('^(?PPRLV( EUROPEEN)? SEPA) (?P.*?)( MDT/.*?)?( ECH/\d+)?( ID .*)?$'),
- FrenchTransaction.TYPE_ORDER),
- (re.compile('^(?PECHEANCEPRET)(?P.*)'), FrenchTransaction.TYPE_LOAN_PAYMENT),
- (re.compile('^(?PRETRAIT DAB) (?P\d{2})/(?P\d{2})/(?P\d{2})( (?P\d+)H(?P\d+))?( \d+)? (?P.*)'),
- FrenchTransaction.TYPE_WITHDRAWAL),
- (re.compile('^(?PVIR(EMEN)?T? (RECU |FAVEUR )?(TIERS )?)\w+ \d+/\d+ \d+H\d+ \w+ (?P.*)$'),
- FrenchTransaction.TYPE_TRANSFER),
- (re.compile('^(?PVIR(EMEN)?T? (EUROPEEN )?(SEPA )?(RECU |FAVEUR |EMIS )?(TIERS )?)(/FRM |/DE |/MOTIF |/BEN )?(?P.*?)(/.+)?$'),
- FrenchTransaction.TYPE_TRANSFER),
- (re.compile('^(?PREMBOURST) CB DU (?P\d{2})(?P\d{2})(?P\d{2}) (?P.*)'),
- FrenchTransaction.TYPE_PAYBACK),
- (re.compile('^(?PREMBOURST)(?P.*)'), FrenchTransaction.TYPE_PAYBACK),
- (re.compile('^(?PCOMMISSIONS)(?P.*)'), FrenchTransaction.TYPE_BANK),
- (re.compile('^(?P(?PREMUNERATION).*)'), FrenchTransaction.TYPE_BANK),
- (re.compile('^(?PREMISE CHEQUES)(?P.*)'), FrenchTransaction.TYPE_DEPOSIT),
- ]
+ PATTERNS = [
+ (re.compile(u'^(?PCHEQUE)(?P.*)'), FrenchTransaction.TYPE_CHECK),
+ (
+ re.compile(
+ '^(?PFACTURE CARTE) DU (?P\d{2})(?P\d{2})(?P\d{2}) (?P.*?)( CA?R?T?E? ?\d*X*\d*)?$'
+ ),
+ FrenchTransaction.TYPE_CARD
+ ),
+ (re.compile('^(?P(PRELEVEMENT|TELEREGLEMENT|TIP)) (?P.*)'), FrenchTransaction.TYPE_ORDER),
+ (
+ re.compile('^(?PPRLV( EUROPEEN)? SEPA) (?P.*?)( MDT/.*?)?( ECH/\d+)?( ID .*)?$'),
+ FrenchTransaction.TYPE_ORDER
+ ),
+ (re.compile('^(?PECHEANCEPRET)(?P.*)'), FrenchTransaction.TYPE_LOAN_PAYMENT),
+ (
+ re.compile(
+ '^(?PRETRAIT DAB) (?P\d{2})/(?P\d{2})/(?P\d{2})( (?P\d+)H(?P\d+))?( \d+)? (?P.*)'
+ ),
+ FrenchTransaction.TYPE_WITHDRAWAL
+ ),
+ (
+ re.compile('^(?PVIR(EMEN)?T? (RECU |FAVEUR )?(TIERS )?)\w+ \d+/\d+ \d+H\d+ \w+ (?P.*)$'),
+ FrenchTransaction.TYPE_TRANSFER
+ ),
+ (
+ re.compile(
+ '^(?PVIR(EMEN)?T? (EUROPEEN )?(SEPA )?(RECU |FAVEUR |EMIS )?(TIERS )?)(/FRM |/DE |/MOTIF |/BEN )?(?P.*?)(/.+)?$'
+ ),
+ FrenchTransaction.TYPE_TRANSFER
+ ),
+ (
+ re.compile('^(?PREMBOURST) CB DU (?P\d{2})(?P\d{2})(?P\d{2}) (?P.*)'),
+ FrenchTransaction.TYPE_PAYBACK
+ ),
+ (re.compile('^(?PREMBOURST)(?P.*)'), FrenchTransaction.TYPE_PAYBACK),
+ (re.compile('^(?PCOMMISSIONS)(?P.*)'), FrenchTransaction.TYPE_BANK),
+ (re.compile('^(?P(?PREMUNERATION).*)'), FrenchTransaction.TYPE_BANK),
+ (re.compile('^(?PREMISE CHEQUES)(?P.*)'), FrenchTransaction.TYPE_DEPOSIT),
+ ]
class HistoryPage(BNPPage):
@@ -631,11 +670,15 @@ def iter_history(self):
'category': op.get('categorie'),
'amount': self.one('montant.montant', op),
})
- tr.parse(raw=CleanText().filter(op.get('libelleOperation')),
- date=parse_french_date(op.get('dateOperation')),
- vdate=parse_french_date(self.one('montant.valueDate', op)))
-
- raw_is_summary = re.match(r'FACTURE CARTE SELON RELEVE DU\b|FACTURE CARTE CARTE AFFAIRES \d{4}X{8}\d{4} SUIVANT\b', tr.raw)
+ tr.parse(
+ raw=CleanText().filter(op.get('libelleOperation')),
+ date=parse_french_date(op.get('dateOperation')),
+ vdate=parse_french_date(self.one('montant.valueDate', op))
+ )
+
+ raw_is_summary = re.match(
+ r'FACTURE CARTE SELON RELEVE DU\b|FACTURE CARTE CARTE AFFAIRES \d{4}X{8}\d{4} SUIVANT\b', tr.raw
+ )
if tr.type == Transaction.TYPE_CARD and raw_is_summary:
tr.type = Transaction.TYPE_CARD_SUMMARY
tr.deleted = True
@@ -658,8 +701,7 @@ def iter_coming(self):
parse_with_patterns(tr.raw, tr, Transaction.PATTERNS)
if tr.type == Transaction.TYPE_CARD:
- tr.type = self.browser.card_to_transaction_type.get(op.get('keyCarte'),
- Transaction.TYPE_DEFERRED_CARD)
+ tr.type = self.browser.card_to_transaction_type.get(op.get('keyCarte'), Transaction.TYPE_DEFERRED_CARD)
yield tr
@@ -708,11 +750,13 @@ def iter_history(self, coming):
'type': Transaction.TYPE_BANK,
'_state': op.get('statut'),
'amount': op.get('montantNet'),
- })
+ })
- tr.parse(date=parse_french_date(op.get('dateSaisie')),
- vdate = parse_french_date(op.get('dateEffet')) if op.get('dateEffet') else None,
- raw='%s %s' % (op.get('libelleMouvement'), op.get('canalSaisie') or ''))
+ tr.parse(
+ date=parse_french_date(op.get('dateSaisie')),
+ vdate=parse_french_date(op.get('dateEffet')) if op.get('dateEffet') else None,
+ raw='%s %s' % (op.get('libelleMouvement'), op.get('canalSaisie') or '')
+ )
tr._op = op
if not tr.amount:
@@ -732,10 +776,10 @@ class NatioVieProPage(BNPPage):
# This form is required to go to the capitalisation contracts page.
def get_params(self):
params = {
- 'app': 'BNPNET',
- 'hageGroup': 'consultationBnpnet',
- 'init': 'true',
- 'multiInit': 'false',
+ 'app': 'BNPNET',
+ 'hageGroup': 'consultationBnpnet',
+ 'init': 'true',
+ 'multiInit': 'false',
}
params['a0'] = self.doc['data']['nationVieProInfos']['a0']
# The number of "p" keys may vary (p0, p1, p2 ... up to p13 or more)
@@ -754,13 +798,13 @@ def has_contracts(self):
# To be completed with other account labels and types seen on the "Assurance Vie" space:
ACCOUNT_TYPES = {
- 'BNP Paribas Multiplacements': Account.TYPE_LIFE_INSURANCE,
- 'BNP Paribas Multihorizons': Account.TYPE_LIFE_INSURANCE,
- 'BNP Paribas Libertéa Privilège': Account.TYPE_LIFE_INSURANCE,
- 'BNP Paribas Avenir Retraite': Account.TYPE_LIFE_INSURANCE,
- 'BNP Paribas Multiciel Privilège': Account.TYPE_CAPITALISATION,
- 'Plan Epargne Retraite Particulier': Account.TYPE_PERP,
- "Plan d'Épargne Retraite des Particuliers": Account.TYPE_PERP,
+ 'BNP Paribas Multiplacements': Account.TYPE_LIFE_INSURANCE,
+ 'BNP Paribas Multihorizons': Account.TYPE_LIFE_INSURANCE,
+ 'BNP Paribas Libertéa Privilège': Account.TYPE_LIFE_INSURANCE,
+ 'BNP Paribas Avenir Retraite': Account.TYPE_LIFE_INSURANCE,
+ 'BNP Paribas Multiciel Privilège': Account.TYPE_CAPITALISATION,
+ 'Plan Epargne Retraite Particulier': Account.TYPE_PERP,
+ "Plan d'Épargne Retraite des Particuliers": Account.TYPE_PERP,
}
@method
@@ -812,7 +856,9 @@ def get_params(self, account):
# The investments vdate is out of the investments table and is the same for all investments:
def get_vdate(self):
- return parse_french_date(CleanText('//table[tr[th[text()[contains(., "Date de valorisation")]]]]/tr[2]/td[2]')(self.doc))
+ return parse_french_date(
+ CleanText('//table[tr[th[text()[contains(., "Date de valorisation")]]]]/tr[2]/td[2]')(self.doc)
+ )
@method
class iter_investments(TableElement):
@@ -832,6 +878,7 @@ class item(ItemElement):
obj_label = CleanText(TableCell('label'))
obj_valuation = CleanDecimal(TableCell('valuation'), replace_dots=True)
obj_portfolio_share = Eval(lambda x: x / 100, CleanDecimal(TableCell('portfolio_share'), replace_dots=True))
+
# There is no "unitvalue" information available on the "Assurances Vie" space.
def obj_quantity(self):
@@ -889,7 +936,7 @@ def iter_history(self):
'amount': op.get('movementAmount'),
'date': datetime.fromtimestamp(op.get('movementDate') / 1000),
'label': op.get('operationName'),
- })
+ })
tr.investments = []
inv = Investment()
@@ -916,7 +963,9 @@ class item(ItemElement):
obj_mobile = CleanText(Dict('data/mobile'), replace=[(' ', '')])
obj_fax = CleanText(Dict('data/fax'), replace=[(' ', '')])
obj_agency = Dict('data/agence')
- obj_address = Format('%s %s %s', Dict('data/adresseAgence'), Dict('data/codePostalAgence'), Dict('data/villeAgence'))
+ obj_address = Format(
+ '%s %s %s', Dict('data/adresseAgence'), Dict('data/codePostalAgence'), Dict('data/villeAgence')
+ )
class AddRecipPage(BNPPage):
diff --git a/modules/bnporc/test.py b/modules/bnporc/test.py
index 0ef44256084a55453b6cb3c8341dbbef28ecb4c1..8d054f47fd5a9ba08ccd8ee4804b4186fb36189e 100644
--- a/modules/bnporc/test.py
+++ b/modules/bnporc/test.py
@@ -17,7 +17,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
-
from weboob.tools.test import BackendTest
from random import choice