From 349815fbc96d00c44b0d0872bb8c4631bf358687 Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Sat, 20 Apr 2019 11:31:27 +0200 Subject: [PATCH] backport modules fixes from master --- modules/{okc => 750g}/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/750g/pages.py | 2 +- modules/adecco/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/adecco/pages.py | 2 +- modules/afer/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/afer/pages.py | 2 +- modules/agendaculturel/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/agendaculturel/pages.py | 2 +- modules/agendadulibre/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/agendadulibre/pages.py | 2 +- modules/allrecipes/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/allrecipes/pages.py | 2 +- modules/amazon/browser.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/amazon/pages.py | 2 +- modules/ameli/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ameli/pages.py | 2 +- modules/americanexpress/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/americanexpress/pages.py | 2 +- modules/amundi/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/amundi/pages.py | 2 +- modules/apec/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/apec/pages.py | 2 +- modules/apivie/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/apivie/pages.py | 2 +- modules/arte/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/arte/pages.py | 2 +- modules/aum/browser.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/avendrealouer/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/avendrealouer/pages.py | 2 +- modules/axabanque/browser.py | 3 + modules/axabanque/pages/bank.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/axabanque/pages/document.py | 2 +- modules/axabanque/pages/login.py | 2 +- modules/axabanque/pages/transfer.py | 13 +- modules/axabanque/pages/wealth.py | 2 +- modules/bandcamp/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bandcamp/pages.py | 2 +- modules/banquepopulaire/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/banquepopulaire/pages.py | 2 +- modules/barclays/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/barclays/pages.py | 2 +- modules/becm/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/becm/pages.py | 2 +- modules/bforbank/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bforbank/pages.py | 2 +- modules/bibliothequesparis/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bibliothequesparis/pages.py | 2 +- modules/billetreduc/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/billetreduc/pages.py | 2 +- modules/binck/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/binck/pages.py | 2 +- modules/biplan/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/biplan/pages.py | 2 +- modules/blablacar/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/blablacar/pages.py | 2 +- modules/blogspot/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/blogspot/pages.py | 2 +- modules/bnpcards/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bnpcards/corporate/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bnpcards/corporate/pages.py | 2 +- modules/bnpcards/pages.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/bnporc/enterprise/pages.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/bnporc/pp/pages.py | 19 +- modules/bnppere/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bnppere/pages.py | 2 +- modules/bolden/browser.py | 6 +- modules/bolden/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bolden/module.py | 1 - modules/bolden/pages.py | 21 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/boursorama/module.py | 3 + modules/boursorama/pages.py | 62 +- modules/bouygues/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bouygues/pages.py | 2 +- modules/bp/browser.py | 3 +- modules/bp/pages/accounthistory.py | 2 +- modules/bp/pages/accountlist.py | 4 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/bp/pages/login.py | 2 +- modules/bp/pages/mandate.py | 2 +- modules/bp/pages/pro.py | 2 +- modules/bp/pages/subscription.py | 2 +- modules/bp/pages/transfer.py | 2 +- modules/bred/bred/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bred/bred/pages.py | 2 +- modules/bred/dispobank/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/bred/dispobank/pages.py | 2 +- modules/btmon/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/btmon/pages.py | 2 +- modules/caels/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/caels/pages.py | 2 +- modules/caissedepargne/cenet/browser.py | 4 +- .../caissedepargne/cenet/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/caissedepargne/cenet/pages.py | 72 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/caissedepargne/pages.py | 9 +- modules/carrefourbanque/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/carrefourbanque/pages.py | 2 +- modules/cci/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cci/pages.py | 2 +- modules/centquatre/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/centquatre/pages.py | 4 +- modules/chronopost/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/chronopost/pages.py | 2 +- modules/cityscoot/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cityscoot/pages.py | 2 +- modules/cmes/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cmes/pages.py | 2 +- modules/cmso/par/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cmso/par/pages.py | 4 +- modules/cmso/par/transfer_pages.py | 2 +- modules/cmso/pro/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cmso/pro/pages.py | 2 +- modules/colissimo/browser.py | 4 +- modules/colissimo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cpasbien/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cpasbien/pages.py | 2 +- modules/cragr/api/browser.py | 18 +- .../compat/weboob_browser_filters_standard.py | 1060 +---------------- modules/cragr/api/pages.py | 2 +- modules/cragr/api/transfer_pages.py | 9 +- modules/cragr/web/browser.py | 4 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/cragr/web/pages.py | 2 +- modules/creditdunord/browser.py | 16 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/creditdunord/pages.py | 22 +- .../compat/weboob_browser_filters_standard.py | 49 + .../weboob_tools_captcha_virtkeyboard.py | 196 --- modules/creditdunordpee/pages.py | 2 +- modules/creditmutuel/browser.py | 1 + modules/creditmutuel/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/creditmutuel/pages.py | 27 +- modules/cuisineaz/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/cuisineaz/pages.py | 2 +- modules/dailymotion/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/dailymotion/pages.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/delubac/pages.py | 2 +- modules/dlfp/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/dlfp/pages/wiki.py | 2 +- modules/dresdenwetter/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/dresdenwetter/pages.py | 2 +- modules/edf/module.py | 2 +- modules/edf/par/browser.py | 124 +- modules/edf/par/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/edf/par/pages.py | 25 +- modules/edf/pro/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/edf/pro/pages.py | 2 +- modules/ekwateur/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ekwateur/pages.py | 2 +- modules/ensap/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ensap/pages.py | 2 +- modules/entreparticuliers/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/entreparticuliers/pages.py | 2 +- modules/explorimmo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/explorimmo/pages.py | 2 +- modules/feedly/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/feedly/pages.py | 2 +- modules/foncia/browser.py | 2 +- modules/foncia/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/foncia/constants.py | 4 +- modules/foncia/pages.py | 19 +- modules/fortuneo/pages/accounts_list.py | 2 +- modules/fortuneo/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/fortuneo/pages/login.py | 2 +- modules/fortuneo/pages/transfer.py | 2 +- modules/francetelevisions/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/francetelevisions/pages.py | 2 +- modules/freemobile/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/freemobile/pages/history.py | 2 +- modules/freemobile/pages/homepage.py | 2 +- modules/freemobile/pages/profile.py | 2 +- modules/freeteknomusic/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/freeteknomusic/pages.py | 2 +- modules/funmooc/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/funmooc/pages.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/genericnewspaper/pages.py | 2 +- modules/gmf/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/gmf/pages.py | 2 +- modules/groupama/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/groupama/pages.py | 2 +- modules/happn/browser.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/hds/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/hds/pages.py | 2 +- modules/hsbc/browser.py | 9 - modules/hsbc/pages/account_pages.py | 2 +- modules/hsbc/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/hsbc/pages/investments.py | 2 +- modules/hsbc/pages/landing_pages.py | 2 +- modules/hsbc/pages/life_insurances.py | 2 +- modules/hybride/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/hybride/pages.py | 2 +- modules/ilmatieteenlaitos/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ilmatieteenlaitos/pages.py | 2 +- modules/ina/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ina/pages.py | 2 +- modules/indeed/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/indeed/pages.py | 2 +- modules/infomaniak/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/infomaniak/pages.py | 2 +- modules/ing/api/accounts_page.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/ing/api/profile_page.py | 2 +- modules/ing/api/transfer_page.py | 2 +- modules/ing/pages/accounts_list.py | 2 +- modules/ing/pages/bills.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + .../weboob_tools_captcha_virtkeyboard.py | 196 --- modules/ing/pages/login.py | 2 +- modules/ing/pages/titre.py | 2 +- modules/ing/pages/transfer.py | 2 +- modules/ing/web/accounts_list.py | 2 +- modules/ing/web/bills.py | 2 +- modules/ing/web/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ing/web/login.py | 2 +- modules/ing/web/titre.py | 2 +- modules/ipinfodb/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ipinfodb/pages.py | 2 +- modules/journaldesfemmes/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/journaldesfemmes/pages.py | 2 +- modules/kickass/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/kickass/pages.py | 2 +- modules/lacentrale/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lacentrale/pages.py | 2 +- modules/lameteoagricole/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lameteoagricole/pages.py | 2 +- modules/lampiris/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lampiris/pages.py | 2 +- modules/larousse/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/larousse/pages.py | 2 +- modules/lcl/browser.py | 5 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/lcl/enterprise/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lcl/enterprise/pages.py | 2 +- modules/lcl/pages.py | 2 +- modules/ldlc/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ldlc/pages.py | 2 +- modules/leboncoin/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/leboncoin/pages.py | 2 +- modules/lefigaro/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lefigaro/pages.py | 2 +- modules/liberation/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/liberation/pages.py | 2 +- modules/limetorrents/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/limetorrents/pages.py | 2 +- modules/linebourse/api/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/linebourse/api/pages.py | 2 +- modules/linebourse/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/linebourse/pages.py | 2 +- modules/linuxjobs/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/linuxjobs/pages.py | 2 +- modules/logicimmo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/logicimmo/pages.py | 2 +- modules/lolix/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lolix/pages.py | 2 +- modules/lyricsdotcom/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lyricsdotcom/pages.py | 2 +- modules/lyricsmode/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lyricsmode/pages.py | 2 +- modules/lyricsplanet/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/lyricsplanet/pages.py | 2 +- modules/manpower/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/manpower/pages.py | 2 +- modules/mareeinfo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/mareeinfo/pages.py | 2 +- modules/marmiton/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/marmiton/pages.py | 2 +- modules/materielnet/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/materielnet/pages.py | 2 +- modules/meslieuxparis/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/meslieuxparis/pages.py | 2 +- modules/meteofrance/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/meteofrance/pages.py | 2 +- modules/minutes20/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/minutes20/pages.py | 2 +- modules/monster/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/monster/pages.py | 2 +- modules/myedenred/browser.py | 10 +- modules/myedenred/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/myedenred/module.py | 2 +- modules/myedenred/pages.py | 33 +- modules/myfoncia/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/myfoncia/pages.py | 2 +- modules/n26/browser.py | 2 +- modules/n26/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/nalo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/nalo/pages.py | 2 +- modules/nef/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/nef/pages.py | 2 +- modules/netfinca/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/netfinca/module.py | 3 +- modules/netfinca/pages.py | 2 +- modules/oney/browser.py | 46 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/oney/pages.py | 2 +- modules/onlinenet/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/onlinenet/pages.py | 2 +- modules/opensubtitles/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/opensubtitles/pages.py | 2 +- modules/orange/pages/bills.py | 2 +- modules/orange/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/orange/pages/login.py | 2 +- modules/orange/pages/profile.py | 2 +- modules/ovh/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ovh/pages.py | 2 +- modules/pagesjaunes/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/pagesjaunes/pages.py | 7 +- modules/pap/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/pap/pages.py | 2 +- modules/paroles2chansons/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/paroles2chansons/pages.py | 2 +- modules/parolesmania/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/parolesmania/pages.py | 2 +- modules/parolesmusique/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/parolesmusique/pages.py | 2 +- modules/parolesnet/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/parolesnet/pages.py | 2 +- modules/pastealacon/browser.py | 2 +- modules/pastealacon/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/pastebin/browser.py | 4 +- modules/pastebin/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/paypal/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/paypal/pages.py | 2 +- modules/phpbb/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/phpbb/pages/forum.py | 2 +- modules/piratebay/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/piratebay/pages/torrents.py | 2 +- modules/podnapisi/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/podnapisi/pages.py | 2 +- modules/poivy/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/poivy/pages.py | 2 +- modules/popolemploi/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/popolemploi/pages.py | 2 +- modules/pornhub/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/pornhub/pages.py | 2 +- modules/prixcarburants/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/prixcarburants/pages.py | 2 +- modules/radiofrance/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/radiofrance/pages.py | 2 +- modules/ratp/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ratp/pages.py | 2 +- modules/razibus/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/razibus/pages.py | 2 +- modules/reddit/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/reddit/pages.py | 2 +- modules/redmine/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/redmine/pages/issues.py | 2 +- modules/regionsjob/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/regionsjob/pages.py | 2 +- modules/residentadvisor/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/residentadvisor/pages.py | 2 +- modules/rmll/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/rmll/pages.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/s2e/pages.py | 2 +- modules/sachsen/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/sachsen/pages.py | 2 +- modules/seloger/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/seloger/pages.py | 2 +- modules/senscritique/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/senscritique/pages.py | 2 +- modules/societegenerale/browser.py | 12 +- .../societegenerale/pages/accounts_list.py | 39 +- modules/societegenerale/pages/base.py | 2 +- .../societegenerale/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/societegenerale/pages/login.py | 2 +- modules/societegenerale/pages/subscription.py | 2 +- modules/societegenerale/pages/transfer.py | 2 +- .../societegenerale/sgpe/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/societegenerale/sgpe/json_pages.py | 2 +- modules/societegenerale/sgpe/pages.py | 2 +- .../societegenerale/sgpe/transfer_pages.py | 4 +- modules/sogecartenet/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/sogecartenet/pages.py | 2 +- modules/spirica/browser.py | 71 +- modules/spirica/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/spirica/pages.py | 10 +- modules/sprunge/browser.py | 2 +- modules/sprunge/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/sueurdemetal/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/sueurdemetal/pages.py | 2 +- modules/supertoinette/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/supertoinette/pages.py | 2 +- modules/suravenir/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/suravenir/pages.py | 2 +- modules/t411/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/t411/pages/torrents.py | 2 +- modules/themisbanque/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/themisbanque/pages.py | 2 +- modules/ticketscesu/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/ticketscesu/pages.py | 2 +- modules/tinder/browser.py | 2 +- modules/tinder/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/torrentz/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/torrentz/pages/torrents.py | 2 +- modules/trainline/browser.py | 2 +- modules/trainline/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/transilien/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/transilien/pages.py | 2 +- modules/tumblr/browser.py | 2 +- modules/tumblr/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/twitter/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/twitter/pages.py | 2 +- modules/vimeo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/vimeo/pages.py | 2 +- modules/vine/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/vine/pages.py | 2 +- modules/vlille/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/vlille/pages.py | 2 +- modules/weather/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/weather/pages.py | 2 +- modules/wordreference/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/wordreference/pages.py | 2 +- modules/xhamster/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/xhamster/pages.py | 2 +- modules/yahoo/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/yahoo/pages.py | 2 +- modules/yggtorrent/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/yggtorrent/pages/torrents.py | 2 +- modules/yomoni/browser.py | 2 +- modules/yomoni/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/youjizz/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/youjizz/pages/index.py | 2 +- modules/youjizz/pages/video.py | 2 +- modules/youporn/pages/compat/__init__.py | 0 .../compat/weboob_browser_filters_standard.py | 49 + modules/youporn/pages/index.py | 2 +- modules/youporn/pages/video.py | 2 +- .../compat/weboob_browser_filters_standard.py | 49 + modules/zerobin/crypto.py | 14 +- modules/zerobin/pages.py | 2 +- 604 files changed, 9862 insertions(+), 1888 deletions(-) rename modules/{okc => 750g}/compat/__init__.py (100%) create mode 100644 modules/750g/compat/weboob_browser_filters_standard.py create mode 100644 modules/adecco/compat/__init__.py create mode 100644 modules/adecco/compat/weboob_browser_filters_standard.py create mode 100644 modules/afer/compat/__init__.py create mode 100644 modules/afer/compat/weboob_browser_filters_standard.py create mode 100644 modules/agendaculturel/compat/__init__.py create mode 100644 modules/agendaculturel/compat/weboob_browser_filters_standard.py create mode 100644 modules/agendadulibre/compat/__init__.py create mode 100644 modules/agendadulibre/compat/weboob_browser_filters_standard.py create mode 100644 modules/allrecipes/compat/__init__.py create mode 100644 modules/allrecipes/compat/weboob_browser_filters_standard.py create mode 100644 modules/amazon/compat/weboob_browser_filters_standard.py create mode 100644 modules/ameli/compat/__init__.py create mode 100644 modules/ameli/compat/weboob_browser_filters_standard.py create mode 100644 modules/americanexpress/compat/__init__.py create mode 100644 modules/americanexpress/compat/weboob_browser_filters_standard.py create mode 100644 modules/amundi/compat/__init__.py create mode 100644 modules/amundi/compat/weboob_browser_filters_standard.py create mode 100644 modules/apec/compat/__init__.py create mode 100644 modules/apec/compat/weboob_browser_filters_standard.py create mode 100644 modules/apivie/compat/__init__.py create mode 100644 modules/apivie/compat/weboob_browser_filters_standard.py create mode 100644 modules/arte/compat/__init__.py create mode 100644 modules/arte/compat/weboob_browser_filters_standard.py create mode 100644 modules/aum/compat/weboob_browser_filters_standard.py create mode 100644 modules/avendrealouer/compat/__init__.py create mode 100644 modules/avendrealouer/compat/weboob_browser_filters_standard.py create mode 100644 modules/axabanque/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/bandcamp/compat/__init__.py create mode 100644 modules/bandcamp/compat/weboob_browser_filters_standard.py create mode 100644 modules/banquepopulaire/compat/__init__.py create mode 100644 modules/banquepopulaire/compat/weboob_browser_filters_standard.py create mode 100644 modules/barclays/compat/__init__.py create mode 100644 modules/barclays/compat/weboob_browser_filters_standard.py create mode 100644 modules/becm/compat/__init__.py create mode 100644 modules/becm/compat/weboob_browser_filters_standard.py create mode 100644 modules/bforbank/compat/__init__.py create mode 100644 modules/bforbank/compat/weboob_browser_filters_standard.py create mode 100644 modules/bibliothequesparis/compat/__init__.py create mode 100644 modules/bibliothequesparis/compat/weboob_browser_filters_standard.py create mode 100644 modules/billetreduc/compat/__init__.py create mode 100644 modules/billetreduc/compat/weboob_browser_filters_standard.py create mode 100644 modules/binck/compat/__init__.py create mode 100644 modules/binck/compat/weboob_browser_filters_standard.py create mode 100644 modules/biplan/compat/__init__.py create mode 100644 modules/biplan/compat/weboob_browser_filters_standard.py create mode 100644 modules/blablacar/compat/__init__.py create mode 100644 modules/blablacar/compat/weboob_browser_filters_standard.py create mode 100644 modules/blogspot/compat/__init__.py create mode 100644 modules/blogspot/compat/weboob_browser_filters_standard.py create mode 100644 modules/bnpcards/compat/__init__.py create mode 100644 modules/bnpcards/compat/weboob_browser_filters_standard.py create mode 100644 modules/bnpcards/corporate/compat/__init__.py create mode 100644 modules/bnpcards/corporate/compat/weboob_browser_filters_standard.py create mode 100644 modules/bnporc/enterprise/compat/weboob_browser_filters_standard.py create mode 100644 modules/bnporc/pp/compat/weboob_browser_filters_standard.py create mode 100644 modules/bnppere/compat/__init__.py create mode 100644 modules/bnppere/compat/weboob_browser_filters_standard.py create mode 100644 modules/bolden/compat/__init__.py create mode 100644 modules/bolden/compat/weboob_browser_filters_standard.py create mode 100644 modules/boursorama/compat/weboob_browser_filters_standard.py create mode 100644 modules/bouygues/compat/__init__.py create mode 100644 modules/bouygues/compat/weboob_browser_filters_standard.py create mode 100644 modules/bp/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/bred/bred/compat/__init__.py create mode 100644 modules/bred/bred/compat/weboob_browser_filters_standard.py create mode 100644 modules/bred/dispobank/compat/__init__.py create mode 100644 modules/bred/dispobank/compat/weboob_browser_filters_standard.py create mode 100644 modules/btmon/compat/__init__.py create mode 100644 modules/btmon/compat/weboob_browser_filters_standard.py create mode 100644 modules/caels/compat/__init__.py create mode 100644 modules/caels/compat/weboob_browser_filters_standard.py create mode 100644 modules/caissedepargne/cenet/compat/__init__.py create mode 100644 modules/caissedepargne/cenet/compat/weboob_browser_filters_standard.py create mode 100644 modules/caissedepargne/compat/weboob_browser_filters_standard.py create mode 100644 modules/carrefourbanque/compat/__init__.py create mode 100644 modules/carrefourbanque/compat/weboob_browser_filters_standard.py create mode 100644 modules/cci/compat/__init__.py create mode 100644 modules/cci/compat/weboob_browser_filters_standard.py create mode 100644 modules/centquatre/compat/__init__.py create mode 100644 modules/centquatre/compat/weboob_browser_filters_standard.py create mode 100644 modules/chronopost/compat/__init__.py create mode 100644 modules/chronopost/compat/weboob_browser_filters_standard.py create mode 100644 modules/cityscoot/compat/__init__.py create mode 100644 modules/cityscoot/compat/weboob_browser_filters_standard.py create mode 100644 modules/cmes/compat/__init__.py create mode 100644 modules/cmes/compat/weboob_browser_filters_standard.py create mode 100644 modules/cmso/par/compat/__init__.py create mode 100644 modules/cmso/par/compat/weboob_browser_filters_standard.py create mode 100644 modules/cmso/pro/compat/__init__.py create mode 100644 modules/cmso/pro/compat/weboob_browser_filters_standard.py create mode 100644 modules/colissimo/compat/__init__.py create mode 100644 modules/colissimo/compat/weboob_browser_filters_standard.py create mode 100644 modules/cpasbien/compat/__init__.py create mode 100644 modules/cpasbien/compat/weboob_browser_filters_standard.py create mode 100644 modules/cragr/web/compat/weboob_browser_filters_standard.py create mode 100644 modules/creditdunord/compat/weboob_browser_filters_standard.py create mode 100644 modules/creditdunordpee/compat/weboob_browser_filters_standard.py delete mode 100644 modules/creditdunordpee/compat/weboob_tools_captcha_virtkeyboard.py create mode 100644 modules/creditmutuel/compat/__init__.py create mode 100644 modules/creditmutuel/compat/weboob_browser_filters_standard.py create mode 100644 modules/cuisineaz/compat/__init__.py create mode 100644 modules/cuisineaz/compat/weboob_browser_filters_standard.py create mode 100644 modules/dailymotion/compat/__init__.py create mode 100644 modules/dailymotion/compat/weboob_browser_filters_standard.py create mode 100644 modules/delubac/compat/weboob_browser_filters_standard.py create mode 100644 modules/dlfp/pages/compat/__init__.py create mode 100644 modules/dlfp/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/dresdenwetter/compat/__init__.py create mode 100644 modules/dresdenwetter/compat/weboob_browser_filters_standard.py create mode 100644 modules/edf/par/compat/__init__.py create mode 100644 modules/edf/par/compat/weboob_browser_filters_standard.py create mode 100644 modules/edf/pro/compat/__init__.py create mode 100644 modules/edf/pro/compat/weboob_browser_filters_standard.py create mode 100644 modules/ekwateur/compat/__init__.py create mode 100644 modules/ekwateur/compat/weboob_browser_filters_standard.py create mode 100644 modules/ensap/compat/__init__.py create mode 100644 modules/ensap/compat/weboob_browser_filters_standard.py create mode 100644 modules/entreparticuliers/compat/__init__.py create mode 100644 modules/entreparticuliers/compat/weboob_browser_filters_standard.py create mode 100644 modules/explorimmo/compat/__init__.py create mode 100644 modules/explorimmo/compat/weboob_browser_filters_standard.py create mode 100644 modules/feedly/compat/__init__.py create mode 100644 modules/feedly/compat/weboob_browser_filters_standard.py create mode 100644 modules/foncia/compat/__init__.py create mode 100644 modules/foncia/compat/weboob_browser_filters_standard.py create mode 100644 modules/fortuneo/pages/compat/__init__.py create mode 100644 modules/fortuneo/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/francetelevisions/compat/__init__.py create mode 100644 modules/francetelevisions/compat/weboob_browser_filters_standard.py create mode 100644 modules/freemobile/pages/compat/__init__.py create mode 100644 modules/freemobile/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/freeteknomusic/compat/__init__.py create mode 100644 modules/freeteknomusic/compat/weboob_browser_filters_standard.py create mode 100644 modules/funmooc/compat/__init__.py create mode 100644 modules/funmooc/compat/weboob_browser_filters_standard.py create mode 100644 modules/genericnewspaper/compat/weboob_browser_filters_standard.py create mode 100644 modules/gmf/compat/__init__.py create mode 100644 modules/gmf/compat/weboob_browser_filters_standard.py create mode 100644 modules/groupama/compat/__init__.py create mode 100644 modules/groupama/compat/weboob_browser_filters_standard.py create mode 100644 modules/happn/compat/weboob_browser_filters_standard.py create mode 100644 modules/hds/compat/__init__.py create mode 100644 modules/hds/compat/weboob_browser_filters_standard.py create mode 100644 modules/hsbc/pages/compat/__init__.py create mode 100644 modules/hsbc/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/hybride/compat/__init__.py create mode 100644 modules/hybride/compat/weboob_browser_filters_standard.py create mode 100644 modules/ilmatieteenlaitos/compat/__init__.py create mode 100644 modules/ilmatieteenlaitos/compat/weboob_browser_filters_standard.py create mode 100644 modules/ina/compat/__init__.py create mode 100644 modules/ina/compat/weboob_browser_filters_standard.py create mode 100644 modules/indeed/compat/__init__.py create mode 100644 modules/indeed/compat/weboob_browser_filters_standard.py create mode 100644 modules/infomaniak/compat/__init__.py create mode 100644 modules/infomaniak/compat/weboob_browser_filters_standard.py create mode 100644 modules/ing/api/compat/weboob_browser_filters_standard.py create mode 100644 modules/ing/pages/compat/weboob_browser_filters_standard.py delete mode 100644 modules/ing/pages/compat/weboob_tools_captcha_virtkeyboard.py create mode 100644 modules/ing/web/compat/__init__.py create mode 100644 modules/ing/web/compat/weboob_browser_filters_standard.py create mode 100644 modules/ipinfodb/compat/__init__.py create mode 100644 modules/ipinfodb/compat/weboob_browser_filters_standard.py create mode 100644 modules/journaldesfemmes/compat/__init__.py create mode 100644 modules/journaldesfemmes/compat/weboob_browser_filters_standard.py create mode 100644 modules/kickass/compat/__init__.py create mode 100644 modules/kickass/compat/weboob_browser_filters_standard.py create mode 100644 modules/lacentrale/compat/__init__.py create mode 100644 modules/lacentrale/compat/weboob_browser_filters_standard.py create mode 100644 modules/lameteoagricole/compat/__init__.py create mode 100644 modules/lameteoagricole/compat/weboob_browser_filters_standard.py create mode 100644 modules/lampiris/compat/__init__.py create mode 100644 modules/lampiris/compat/weboob_browser_filters_standard.py create mode 100644 modules/larousse/compat/__init__.py create mode 100644 modules/larousse/compat/weboob_browser_filters_standard.py create mode 100644 modules/lcl/compat/weboob_browser_filters_standard.py create mode 100644 modules/lcl/enterprise/compat/__init__.py create mode 100644 modules/lcl/enterprise/compat/weboob_browser_filters_standard.py create mode 100644 modules/ldlc/compat/__init__.py create mode 100644 modules/ldlc/compat/weboob_browser_filters_standard.py create mode 100644 modules/leboncoin/compat/__init__.py create mode 100644 modules/leboncoin/compat/weboob_browser_filters_standard.py create mode 100644 modules/lefigaro/compat/__init__.py create mode 100644 modules/lefigaro/compat/weboob_browser_filters_standard.py create mode 100644 modules/liberation/compat/__init__.py create mode 100644 modules/liberation/compat/weboob_browser_filters_standard.py create mode 100644 modules/limetorrents/compat/__init__.py create mode 100644 modules/limetorrents/compat/weboob_browser_filters_standard.py create mode 100644 modules/linebourse/api/compat/__init__.py create mode 100644 modules/linebourse/api/compat/weboob_browser_filters_standard.py create mode 100644 modules/linebourse/compat/__init__.py create mode 100644 modules/linebourse/compat/weboob_browser_filters_standard.py create mode 100644 modules/linuxjobs/compat/__init__.py create mode 100644 modules/linuxjobs/compat/weboob_browser_filters_standard.py create mode 100644 modules/logicimmo/compat/__init__.py create mode 100644 modules/logicimmo/compat/weboob_browser_filters_standard.py create mode 100644 modules/lolix/compat/__init__.py create mode 100644 modules/lolix/compat/weboob_browser_filters_standard.py create mode 100644 modules/lyricsdotcom/compat/__init__.py create mode 100644 modules/lyricsdotcom/compat/weboob_browser_filters_standard.py create mode 100644 modules/lyricsmode/compat/__init__.py create mode 100644 modules/lyricsmode/compat/weboob_browser_filters_standard.py create mode 100644 modules/lyricsplanet/compat/__init__.py create mode 100644 modules/lyricsplanet/compat/weboob_browser_filters_standard.py create mode 100644 modules/manpower/compat/__init__.py create mode 100644 modules/manpower/compat/weboob_browser_filters_standard.py create mode 100644 modules/mareeinfo/compat/__init__.py create mode 100644 modules/mareeinfo/compat/weboob_browser_filters_standard.py create mode 100644 modules/marmiton/compat/__init__.py create mode 100644 modules/marmiton/compat/weboob_browser_filters_standard.py create mode 100644 modules/materielnet/compat/__init__.py create mode 100644 modules/materielnet/compat/weboob_browser_filters_standard.py create mode 100644 modules/meslieuxparis/compat/__init__.py create mode 100644 modules/meslieuxparis/compat/weboob_browser_filters_standard.py create mode 100644 modules/meteofrance/compat/__init__.py create mode 100644 modules/meteofrance/compat/weboob_browser_filters_standard.py create mode 100644 modules/minutes20/compat/__init__.py create mode 100644 modules/minutes20/compat/weboob_browser_filters_standard.py create mode 100644 modules/monster/compat/__init__.py create mode 100644 modules/monster/compat/weboob_browser_filters_standard.py create mode 100644 modules/myedenred/compat/__init__.py create mode 100644 modules/myedenred/compat/weboob_browser_filters_standard.py create mode 100644 modules/myfoncia/compat/__init__.py create mode 100644 modules/myfoncia/compat/weboob_browser_filters_standard.py create mode 100644 modules/n26/compat/__init__.py create mode 100644 modules/n26/compat/weboob_browser_filters_standard.py create mode 100644 modules/nalo/compat/__init__.py create mode 100644 modules/nalo/compat/weboob_browser_filters_standard.py create mode 100644 modules/nef/compat/__init__.py create mode 100644 modules/nef/compat/weboob_browser_filters_standard.py create mode 100644 modules/netfinca/compat/__init__.py create mode 100644 modules/netfinca/compat/weboob_browser_filters_standard.py create mode 100644 modules/oney/compat/weboob_browser_filters_standard.py create mode 100644 modules/onlinenet/compat/__init__.py create mode 100644 modules/onlinenet/compat/weboob_browser_filters_standard.py create mode 100644 modules/opensubtitles/compat/__init__.py create mode 100644 modules/opensubtitles/compat/weboob_browser_filters_standard.py create mode 100644 modules/orange/pages/compat/__init__.py create mode 100644 modules/orange/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/ovh/compat/__init__.py create mode 100644 modules/ovh/compat/weboob_browser_filters_standard.py create mode 100644 modules/pagesjaunes/compat/__init__.py create mode 100644 modules/pagesjaunes/compat/weboob_browser_filters_standard.py create mode 100644 modules/pap/compat/__init__.py create mode 100644 modules/pap/compat/weboob_browser_filters_standard.py create mode 100644 modules/paroles2chansons/compat/__init__.py create mode 100644 modules/paroles2chansons/compat/weboob_browser_filters_standard.py create mode 100644 modules/parolesmania/compat/__init__.py create mode 100644 modules/parolesmania/compat/weboob_browser_filters_standard.py create mode 100644 modules/parolesmusique/compat/__init__.py create mode 100644 modules/parolesmusique/compat/weboob_browser_filters_standard.py create mode 100644 modules/parolesnet/compat/__init__.py create mode 100644 modules/parolesnet/compat/weboob_browser_filters_standard.py create mode 100644 modules/pastealacon/compat/__init__.py create mode 100644 modules/pastealacon/compat/weboob_browser_filters_standard.py create mode 100644 modules/pastebin/compat/__init__.py create mode 100644 modules/pastebin/compat/weboob_browser_filters_standard.py create mode 100644 modules/paypal/compat/__init__.py create mode 100644 modules/paypal/compat/weboob_browser_filters_standard.py create mode 100644 modules/phpbb/pages/compat/__init__.py create mode 100644 modules/phpbb/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/piratebay/pages/compat/__init__.py create mode 100644 modules/piratebay/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/podnapisi/compat/__init__.py create mode 100644 modules/podnapisi/compat/weboob_browser_filters_standard.py create mode 100644 modules/poivy/compat/__init__.py create mode 100644 modules/poivy/compat/weboob_browser_filters_standard.py create mode 100644 modules/popolemploi/compat/__init__.py create mode 100644 modules/popolemploi/compat/weboob_browser_filters_standard.py create mode 100644 modules/pornhub/compat/__init__.py create mode 100644 modules/pornhub/compat/weboob_browser_filters_standard.py create mode 100644 modules/prixcarburants/compat/__init__.py create mode 100644 modules/prixcarburants/compat/weboob_browser_filters_standard.py create mode 100644 modules/radiofrance/compat/__init__.py create mode 100644 modules/radiofrance/compat/weboob_browser_filters_standard.py create mode 100644 modules/ratp/compat/__init__.py create mode 100644 modules/ratp/compat/weboob_browser_filters_standard.py create mode 100644 modules/razibus/compat/__init__.py create mode 100644 modules/razibus/compat/weboob_browser_filters_standard.py create mode 100644 modules/reddit/compat/__init__.py create mode 100644 modules/reddit/compat/weboob_browser_filters_standard.py create mode 100644 modules/redmine/pages/compat/__init__.py create mode 100644 modules/redmine/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/regionsjob/compat/__init__.py create mode 100644 modules/regionsjob/compat/weboob_browser_filters_standard.py create mode 100644 modules/residentadvisor/compat/__init__.py create mode 100644 modules/residentadvisor/compat/weboob_browser_filters_standard.py create mode 100644 modules/rmll/compat/__init__.py create mode 100644 modules/rmll/compat/weboob_browser_filters_standard.py create mode 100644 modules/s2e/compat/weboob_browser_filters_standard.py create mode 100644 modules/sachsen/compat/__init__.py create mode 100644 modules/sachsen/compat/weboob_browser_filters_standard.py create mode 100644 modules/seloger/compat/__init__.py create mode 100644 modules/seloger/compat/weboob_browser_filters_standard.py create mode 100644 modules/senscritique/compat/__init__.py create mode 100644 modules/senscritique/compat/weboob_browser_filters_standard.py create mode 100644 modules/societegenerale/pages/compat/__init__.py create mode 100644 modules/societegenerale/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/societegenerale/sgpe/compat/__init__.py create mode 100644 modules/societegenerale/sgpe/compat/weboob_browser_filters_standard.py create mode 100644 modules/sogecartenet/compat/__init__.py create mode 100644 modules/sogecartenet/compat/weboob_browser_filters_standard.py create mode 100644 modules/spirica/compat/__init__.py create mode 100644 modules/spirica/compat/weboob_browser_filters_standard.py create mode 100644 modules/sprunge/compat/__init__.py create mode 100644 modules/sprunge/compat/weboob_browser_filters_standard.py create mode 100644 modules/sueurdemetal/compat/__init__.py create mode 100644 modules/sueurdemetal/compat/weboob_browser_filters_standard.py create mode 100644 modules/supertoinette/compat/__init__.py create mode 100644 modules/supertoinette/compat/weboob_browser_filters_standard.py create mode 100644 modules/suravenir/compat/__init__.py create mode 100644 modules/suravenir/compat/weboob_browser_filters_standard.py create mode 100644 modules/t411/pages/compat/__init__.py create mode 100644 modules/t411/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/themisbanque/compat/__init__.py create mode 100644 modules/themisbanque/compat/weboob_browser_filters_standard.py create mode 100644 modules/ticketscesu/compat/__init__.py create mode 100644 modules/ticketscesu/compat/weboob_browser_filters_standard.py create mode 100644 modules/tinder/compat/__init__.py create mode 100644 modules/tinder/compat/weboob_browser_filters_standard.py create mode 100644 modules/torrentz/pages/compat/__init__.py create mode 100644 modules/torrentz/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/trainline/compat/__init__.py create mode 100644 modules/trainline/compat/weboob_browser_filters_standard.py create mode 100644 modules/transilien/compat/__init__.py create mode 100644 modules/transilien/compat/weboob_browser_filters_standard.py create mode 100644 modules/tumblr/compat/__init__.py create mode 100644 modules/tumblr/compat/weboob_browser_filters_standard.py create mode 100644 modules/twitter/compat/__init__.py create mode 100644 modules/twitter/compat/weboob_browser_filters_standard.py create mode 100644 modules/vimeo/compat/__init__.py create mode 100644 modules/vimeo/compat/weboob_browser_filters_standard.py create mode 100644 modules/vine/compat/__init__.py create mode 100644 modules/vine/compat/weboob_browser_filters_standard.py create mode 100644 modules/vlille/compat/__init__.py create mode 100644 modules/vlille/compat/weboob_browser_filters_standard.py create mode 100644 modules/weather/compat/__init__.py create mode 100644 modules/weather/compat/weboob_browser_filters_standard.py create mode 100644 modules/wordreference/compat/__init__.py create mode 100644 modules/wordreference/compat/weboob_browser_filters_standard.py create mode 100644 modules/xhamster/compat/__init__.py create mode 100644 modules/xhamster/compat/weboob_browser_filters_standard.py create mode 100644 modules/yahoo/compat/__init__.py create mode 100644 modules/yahoo/compat/weboob_browser_filters_standard.py create mode 100644 modules/yggtorrent/pages/compat/__init__.py create mode 100644 modules/yggtorrent/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/yomoni/compat/__init__.py create mode 100644 modules/yomoni/compat/weboob_browser_filters_standard.py create mode 100644 modules/youjizz/pages/compat/__init__.py create mode 100644 modules/youjizz/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/youporn/pages/compat/__init__.py create mode 100644 modules/youporn/pages/compat/weboob_browser_filters_standard.py create mode 100644 modules/zerobin/compat/weboob_browser_filters_standard.py diff --git a/modules/okc/compat/__init__.py b/modules/750g/compat/__init__.py similarity index 100% rename from modules/okc/compat/__init__.py rename to modules/750g/compat/__init__.py diff --git a/modules/750g/compat/weboob_browser_filters_standard.py b/modules/750g/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/750g/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/750g/pages.py b/modules/750g/pages.py index dc3a94819a..555b9f8470 100644 --- a/modules/750g/pages.py +++ b/modules/750g/pages.py @@ -23,7 +23,7 @@ from weboob.capabilities.image import BaseImage, Thumbnail from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Env, CleanDecimal, Eval +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env, CleanDecimal, Eval from weboob.browser.filters.json import Dict, NotFound from datetime import datetime, date, time from dateutil.parser import parse as parse_date diff --git a/modules/adecco/compat/__init__.py b/modules/adecco/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/adecco/compat/weboob_browser_filters_standard.py b/modules/adecco/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/adecco/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/adecco/pages.py b/modules/adecco/pages.py index c932571593..68608bf16c 100644 --- a/modules/adecco/pages.py +++ b/modules/adecco/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage, pagination, JsonPage from weboob.browser.elements import ItemElement, method, DictElement -from weboob.browser.filters.standard import CleanText, Regexp, Date +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Date from weboob.browser.filters.html import CleanHTML from weboob.browser.filters.json import Dict diff --git a/modules/afer/compat/__init__.py b/modules/afer/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/afer/compat/weboob_browser_filters_standard.py b/modules/afer/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/afer/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/afer/pages.py b/modules/afer/pages.py index b5fbe27071..341ec3d371 100644 --- a/modules/afer/pages.py +++ b/modules/afer/pages.py @@ -24,7 +24,7 @@ import requests from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Regexp, CleanDecimal, Date, Async, BrowserURL +from .compat.weboob_browser_filters_standard import CleanText, Regexp, CleanDecimal, Date, Async, BrowserURL from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.capabilities.bank import Account, Investment, Transaction from weboob.capabilities.base import NotAvailable diff --git a/modules/agendaculturel/compat/__init__.py b/modules/agendaculturel/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/agendaculturel/compat/weboob_browser_filters_standard.py b/modules/agendaculturel/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/agendaculturel/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/agendaculturel/pages.py b/modules/agendaculturel/pages.py index 4da6855eb7..7db022564e 100644 --- a/modules/agendaculturel/pages.py +++ b/modules/agendaculturel/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Date, Regexp, Filter, Env, Format, Decode, Time, Type +from .compat.weboob_browser_filters_standard import CleanText, Date, Regexp, Filter, Env, Format, Decode, Time, Type from weboob.browser.filters.html import CleanHTML, XPath from weboob.browser.filters.json import Dict diff --git a/modules/agendadulibre/compat/__init__.py b/modules/agendadulibre/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/agendadulibre/compat/weboob_browser_filters_standard.py b/modules/agendadulibre/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/agendadulibre/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/agendadulibre/pages.py b/modules/agendadulibre/pages.py index f5a1f170df..a825dd8e78 100644 --- a/modules/agendadulibre/pages.py +++ b/modules/agendadulibre/pages.py @@ -24,7 +24,7 @@ from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Regexp, CleanText, DateTime, Env, Format, BrowserURL +from .compat.weboob_browser_filters_standard import Regexp, CleanText, DateTime, Env, Format, BrowserURL from weboob.browser.filters.html import Link, XPath, CleanHTML from weboob.tools.date import parse_french_date diff --git a/modules/allrecipes/compat/__init__.py b/modules/allrecipes/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/allrecipes/compat/weboob_browser_filters_standard.py b/modules/allrecipes/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/allrecipes/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/allrecipes/pages.py b/modules/allrecipes/pages.py index 51d9c8f49c..6655071dbb 100644 --- a/modules/allrecipes/pages.py +++ b/modules/allrecipes/pages.py @@ -23,7 +23,7 @@ from weboob.capabilities.recipe import Recipe, Comment from weboob.capabilities.base import NotAvailable from weboob.capabilities.image import BaseImage, Thumbnail -from weboob.browser.filters.standard import Env, Format, Join, Eval +from .compat.weboob_browser_filters_standard import Env, Format, Join, Eval from weboob.browser.filters.json import Dict diff --git a/modules/amazon/browser.py b/modules/amazon/browser.py index feeb28bf6d..cf1b096445 100644 --- a/modules/amazon/browser.py +++ b/modules/amazon/browser.py @@ -175,7 +175,7 @@ def do_login(self): self.handle_captcha(captcha) else: msg = self.page.get_error_message() - assert self.WRONGPASS_MESSAGE in msg, msg + assert any(wrongpass_message in msg for wrongpass_message in self.WRONGPASS_MESSAGES), msg raise BrowserIncorrectPassword(msg) def is_login(self): diff --git a/modules/amazon/compat/weboob_browser_filters_standard.py b/modules/amazon/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/amazon/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/amazon/pages.py b/modules/amazon/pages.py index 68d191eaee..59aa04e30b 100644 --- a/modules/amazon/pages.py +++ b/modules/amazon/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, FormNotFound, PartialHTMLPage from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.filters.html import Link -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Env, Regexp, Format, Field, Currency, RegexpError, Date, Async, AsyncLoad ) diff --git a/modules/ameli/compat/__init__.py b/modules/ameli/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ameli/compat/weboob_browser_filters_standard.py b/modules/ameli/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ameli/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ameli/pages.py b/modules/ameli/pages.py index 2a91cfee57..f60c2d2f41 100644 --- a/modules/ameli/pages.py +++ b/modules/ameli/pages.py @@ -26,7 +26,7 @@ from weboob.browser.filters.html import Attr, XPathNotFound from weboob.browser.pages import HTMLPage, RawPage, LoggedPage from weboob.capabilities.bill import DocumentTypes, Subscription, Detail, Bill -from weboob.browser.filters.standard import CleanText, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Regexp from weboob.exceptions import BrowserUnavailable diff --git a/modules/americanexpress/compat/__init__.py b/modules/americanexpress/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/americanexpress/compat/weboob_browser_filters_standard.py b/modules/americanexpress/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/americanexpress/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/americanexpress/pages.py b/modules/americanexpress/pages.py index 2eca4bcb5a..38684cda81 100644 --- a/modules/americanexpress/pages.py +++ b/modules/americanexpress/pages.py @@ -25,7 +25,7 @@ from weboob.browser.pages import LoggedPage, JsonPage, HTMLPage from weboob.browser.elements import ItemElement, DictElement, method -from weboob.browser.filters.standard import Date, Eval, CleanText, Field, CleanDecimal +from .compat.weboob_browser_filters_standard import Date, Eval, CleanText, Field, CleanDecimal from weboob.browser.filters.json import Dict from weboob.capabilities.bank import Account, Transaction from weboob.capabilities.base import NotAvailable diff --git a/modules/amundi/compat/__init__.py b/modules/amundi/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/amundi/compat/weboob_browser_filters_standard.py b/modules/amundi/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/amundi/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/amundi/pages.py b/modules/amundi/pages.py index 639e05f6ef..056bd6790c 100644 --- a/modules/amundi/pages.py +++ b/modules/amundi/pages.py @@ -22,7 +22,7 @@ from datetime import datetime from weboob.browser.elements import ItemElement, method, DictElement -from weboob.browser.filters.standard import CleanDecimal, Date, Field, CleanText, Env +from .compat.weboob_browser_filters_standard import CleanDecimal, Date, Field, CleanText, Env from weboob.browser.filters.json import Dict from weboob.browser.pages import LoggedPage, JsonPage from weboob.capabilities.bank import Account, Investment, Transaction diff --git a/modules/apec/compat/__init__.py b/modules/apec/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/apec/compat/weboob_browser_filters_standard.py b/modules/apec/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/apec/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/apec/pages.py b/modules/apec/pages.py index 455b7e03bb..f6bebe51f8 100644 --- a/modules/apec/pages.py +++ b/modules/apec/pages.py @@ -22,7 +22,7 @@ from weboob.browser.elements import ItemElement, method, DictElement from weboob.browser.pages import JsonPage, pagination -from weboob.browser.filters.standard import DateTime, Format, Regexp +from .compat.weboob_browser_filters_standard import DateTime, Format, Regexp from weboob.browser.filters.json import Dict from weboob.browser.filters.html import CleanHTML from weboob.capabilities.job import BaseJobAdvert diff --git a/modules/apivie/compat/__init__.py b/modules/apivie/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/apivie/compat/weboob_browser_filters_standard.py b/modules/apivie/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/apivie/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/apivie/pages.py b/modules/apivie/pages.py index a09ee01047..ba85a88a73 100644 --- a/modules/apivie/pages.py +++ b/modules/apivie/pages.py @@ -24,7 +24,7 @@ from weboob.capabilities.base import NotAvailable from weboob.browser.pages import LoggedPage, HTMLPage from weboob.tools.capabilities.bank.transactions import FrenchTransaction -from weboob.browser.filters.standard import Date, CleanText +from .compat.weboob_browser_filters_standard import Date, CleanText from weboob.browser.filters.html import Attr diff --git a/modules/arte/compat/__init__.py b/modules/arte/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/arte/compat/weboob_browser_filters_standard.py b/modules/arte/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/arte/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/arte/pages.py b/modules/arte/pages.py index 87002d4cb5..31d3acc1a9 100644 --- a/modules/arte/pages.py +++ b/modules/arte/pages.py @@ -26,7 +26,7 @@ from weboob.capabilities.video import BaseVideo from weboob.browser.pages import HTMLPage, JsonPage, pagination from weboob.browser.elements import DictElement, ItemElement, ListElement, method -from weboob.browser.filters.standard import Date, Env, CleanText, Field, ItemNotFound, BrowserURL +from .compat.weboob_browser_filters_standard import Date, Env, CleanText, Field, ItemNotFound, BrowserURL from weboob.browser.filters.json import Dict from weboob.tools.date import parse_french_date from weboob.tools.compat import basestring diff --git a/modules/aum/browser.py b/modules/aum/browser.py index 4869c5dd08..37f3c97bec 100644 --- a/modules/aum/browser.py +++ b/modules/aum/browser.py @@ -28,7 +28,7 @@ from weboob.browser.exceptions import ClientError from weboob.browser.browsers import LoginBrowser, DomainBrowser from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.tools.date import local2utc from weboob.capabilities.messages import CantSendMessage diff --git a/modules/aum/compat/weboob_browser_filters_standard.py b/modules/aum/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/aum/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/avendrealouer/compat/__init__.py b/modules/avendrealouer/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/avendrealouer/compat/weboob_browser_filters_standard.py b/modules/avendrealouer/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/avendrealouer/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/avendrealouer/pages.py b/modules/avendrealouer/pages.py index c1d82a8176..ad2433d25b 100644 --- a/modules/avendrealouer/pages.py +++ b/modules/avendrealouer/pages.py @@ -26,7 +26,7 @@ from weboob.browser.filters.html import Attr, AbsoluteLink, Link from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanDecimal, CleanText, Date, Regexp, Async, AsyncLoad +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Date, Regexp, Async, AsyncLoad from weboob.capabilities.housing import City, Housing, UTILITIES, HousingPhoto from weboob.capabilities.base import NotAvailable, Currency diff --git a/modules/axabanque/browser.py b/modules/axabanque/browser.py index b1efe82ce5..0bd8ad196a 100644 --- a/modules/axabanque/browser.py +++ b/modules/axabanque/browser.py @@ -451,6 +451,9 @@ def new_recipient(self, recipient, **params): # Confirm that user want to add recipient self.page.continue_new_recipient() + if self.recipient_confirmation_page.is_here(): + self.page.check_errors() + assert self.add_recipient.is_here() self.page.set_new_recipient_iban(recipient.iban) rcpt = self.copy_recipient_obj(recipient) diff --git a/modules/axabanque/pages/bank.py b/modules/axabanque/pages/bank.py index e4678e5980..850cdc0b51 100644 --- a/modules/axabanque/pages/bank.py +++ b/modules/axabanque/pages/bank.py @@ -25,7 +25,7 @@ from weboob.exceptions import BrowserUnavailable from weboob.browser.pages import HTMLPage, PDFPage, LoggedPage, AbstractPage from weboob.browser.elements import ItemElement, TableElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Date, Regexp, Field, Env, Currency +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Date, Regexp, Field, Env, Currency from weboob.browser.filters.html import Attr, Link, TableCell from weboob.capabilities.bank import Account, Investment from weboob.tools.capabilities.bank.iban import is_iban_valid diff --git a/modules/axabanque/pages/compat/weboob_browser_filters_standard.py b/modules/axabanque/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/axabanque/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/axabanque/pages/document.py b/modules/axabanque/pages/document.py index 3f2228c8cb..b4319c8347 100644 --- a/modules/axabanque/pages/document.py +++ b/modules/axabanque/pages/document.py @@ -18,7 +18,7 @@ # along with this weboob module. If not, see . from weboob.browser.pages import HTMLPage, LoggedPage -from weboob.browser.filters.standard import CleanText, Env, Regexp, Format +from .compat.weboob_browser_filters_standard import CleanText, Env, Regexp, Format from weboob.browser.elements import ListElement, ItemElement, method, SkipItem from weboob.capabilities.bill import Document from weboob.tools.compat import urljoin diff --git a/modules/axabanque/pages/login.py b/modules/axabanque/pages/login.py index e954834151..faacf2d9a1 100644 --- a/modules/axabanque/pages/login.py +++ b/modules/axabanque/pages/login.py @@ -23,7 +23,7 @@ from weboob.exceptions import BrowserBanned, ActionNeeded, BrowserUnavailable from weboob.browser.pages import HTMLPage, RawPage, JsonPage, PartialHTMLPage from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from .compat.weboob_tools_captcha_virtkeyboard import VirtKeyboard, VirtKeyboardError diff --git a/modules/axabanque/pages/transfer.py b/modules/axabanque/pages/transfer.py index 1c479d39f4..9cefbaa66d 100644 --- a/modules/axabanque/pages/transfer.py +++ b/modules/axabanque/pages/transfer.py @@ -28,7 +28,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, TableElement, ItemElement from weboob.browser.filters.html import TableCell -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Date, Regexp, CleanDecimal, Currency, Format, Field, ) from weboob.capabilities.bank import ( @@ -148,6 +148,17 @@ def send_code(self, code): def is_add_recipient_confirmation(self): return self.doc.xpath('//table[@id="idConfirmation"]//p[contains(., "Votre bénéficiaire est en cours de création automatique")]') + def check_errors(self): + # check if user can add new recipient + errors_id = ('popinClientNonEligible', 'popinClientNonEligibleBis') + + for error_id in errors_id: + if self.doc.xpath('//script[contains(text(), "showDivJQInfo(\'%s\')")]' % error_id): + msg = CleanText('//div[@id="%s"]//p' % error_id)(self.doc) + # get the first sentence of information message + # beacause the message is too long and contains unnecessary recommendations + raise AddRecipientBankError(message=msg.split('.')[0]) + class AddRecipientPage(LoggedPage, HTMLPage): is_here = '//table[@id="tab_SaisieBenef"]' diff --git a/modules/axabanque/pages/wealth.py b/modules/axabanque/pages/wealth.py index 1b13f73eaf..556a0692a1 100644 --- a/modules/axabanque/pages/wealth.py +++ b/modules/axabanque/pages/wealth.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, ItemElement, method, TableElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Date, Regexp, CleanDecimal, Eval, Field, Async, AsyncLoad, QueryValue, Currency, ) diff --git a/modules/bandcamp/compat/__init__.py b/modules/bandcamp/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bandcamp/compat/weboob_browser_filters_standard.py b/modules/bandcamp/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bandcamp/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bandcamp/pages.py b/modules/bandcamp/pages.py index 5e3332c106..5a1df8a02e 100644 --- a/modules/bandcamp/pages.py +++ b/modules/bandcamp/pages.py @@ -24,7 +24,7 @@ from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Date, Env, Field, Format +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Date, Env, Field, Format from weboob.browser.filters.html import AbsoluteLink, Attr from weboob.capabilities.collection import Collection from weboob.capabilities.audio import BaseAudio, Album diff --git a/modules/banquepopulaire/compat/__init__.py b/modules/banquepopulaire/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/banquepopulaire/compat/weboob_browser_filters_standard.py b/modules/banquepopulaire/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/banquepopulaire/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/banquepopulaire/pages.py b/modules/banquepopulaire/pages.py index 2fe5c67340..c19459e744 100644 --- a/modules/banquepopulaire/pages.py +++ b/modules/banquepopulaire/pages.py @@ -26,7 +26,7 @@ import sys from weboob.browser.elements import method, DictElement, ItemElement -from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, Eval, Date, Field +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Regexp, Eval, Date, Field from weboob.browser.filters.html import Attr, Link, AttributeNotFound from weboob.browser.filters.json import Dict from weboob.exceptions import BrowserUnavailable, BrowserIncorrectPassword, ActionNeeded diff --git a/modules/barclays/compat/__init__.py b/modules/barclays/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/barclays/compat/weboob_browser_filters_standard.py b/modules/barclays/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/barclays/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/barclays/pages.py b/modules/barclays/pages.py index fe2158464e..c5ca4670ea 100644 --- a/modules/barclays/pages.py +++ b/modules/barclays/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, PDFPage, LoggedPage from weboob.browser.elements import TableElement, ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, Field, Date, Eval +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Regexp, Field, Date, Eval from weboob.browser.filters.html import Attr, TableCell, ReplaceEntities from weboob.capabilities.bank import Account, Investment, Loan, NotAvailable from weboob.tools.capabilities.bank.transactions import FrenchTransaction diff --git a/modules/becm/compat/__init__.py b/modules/becm/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/becm/compat/weboob_browser_filters_standard.py b/modules/becm/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/becm/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/becm/pages.py b/modules/becm/pages.py index 4416c07558..4808f235d9 100644 --- a/modules/becm/pages.py +++ b/modules/becm/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, ItemElement -from weboob.browser.filters.standard import CleanText, Format +from .compat.weboob_browser_filters_standard import CleanText, Format from weboob.capabilities import NotAvailable from weboob.exceptions import BrowserIncorrectPassword diff --git a/modules/bforbank/compat/__init__.py b/modules/bforbank/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bforbank/compat/weboob_browser_filters_standard.py b/modules/bforbank/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bforbank/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bforbank/pages.py b/modules/bforbank/pages.py index e2710166a4..4477c5b208 100644 --- a/modules/bforbank/pages.py +++ b/modules/bforbank/pages.py @@ -31,7 +31,7 @@ from weboob.browser.elements import method, ListElement, ItemElement, TableElement from weboob.capabilities.bank import Account from weboob.browser.filters.html import Link, Attr, TableCell -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Regexp, Field, Map, CleanDecimal, Date, Format, ) from weboob.tools.capabilities.bank.transactions import FrenchTransaction diff --git a/modules/bibliothequesparis/compat/__init__.py b/modules/bibliothequesparis/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bibliothequesparis/compat/weboob_browser_filters_standard.py b/modules/bibliothequesparis/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bibliothequesparis/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bibliothequesparis/pages.py b/modules/bibliothequesparis/pages.py index cce7d9b3b2..ae623acf83 100644 --- a/modules/bibliothequesparis/pages.py +++ b/modules/bibliothequesparis/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage from weboob.browser.elements import ListElement, ItemElement, method, DictElement -from weboob.browser.filters.standard import CleanText, Date, Regexp, Field +from .compat.weboob_browser_filters_standard import CleanText, Date, Regexp, Field from weboob.browser.filters.html import Link from weboob.browser.filters.json import Dict from weboob.capabilities.base import UserError diff --git a/modules/billetreduc/compat/__init__.py b/modules/billetreduc/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/billetreduc/compat/weboob_browser_filters_standard.py b/modules/billetreduc/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/billetreduc/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/billetreduc/pages.py b/modules/billetreduc/pages.py index e120ad253a..d8e669cf21 100644 --- a/modules/billetreduc/pages.py +++ b/modules/billetreduc/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import method, ListElement, ItemElement from weboob.browser.filters.html import AbsoluteLink -from weboob.browser.filters.standard import CleanText, Env, Field, Format +from .compat.weboob_browser_filters_standard import CleanText, Env, Field, Format from weboob.browser.pages import HTMLPage, pagination from weboob.capabilities.base import StringField from weboob.capabilities.calendar import BaseCalendarEvent, CATEGORIES diff --git a/modules/binck/compat/__init__.py b/modules/binck/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/binck/compat/weboob_browser_filters_standard.py b/modules/binck/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/binck/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/binck/pages.py b/modules/binck/pages.py index b00f3a0172..cf0bc81166 100644 --- a/modules/binck/pages.py +++ b/modules/binck/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage from weboob.browser.elements import ItemElement, ListElement, DictElement, TableElement, method -from weboob.browser.filters.standard import CleanText, Date, Format, CleanDecimal, Eval, Env, Field +from .compat.weboob_browser_filters_standard import CleanText, Date, Format, CleanDecimal, Eval, Env, Field from weboob.browser.filters.html import Attr, Link, TableCell from weboob.browser.filters.json import Dict from weboob.exceptions import BrowserPasswordExpired, ActionNeeded diff --git a/modules/biplan/compat/__init__.py b/modules/biplan/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/biplan/compat/weboob_browser_filters_standard.py b/modules/biplan/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/biplan/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/biplan/pages.py b/modules/biplan/pages.py index ce86595c8c..4cac16d8bc 100644 --- a/modules/biplan/pages.py +++ b/modules/biplan/pages.py @@ -27,7 +27,7 @@ from weboob.browser.elements import ItemElement, SkipItem, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Filter, CleanText, Env, Regexp, CombineDate +from .compat.weboob_browser_filters_standard import Filter, CleanText, Env, Regexp, CombineDate from weboob.browser.filters.html import Link, CleanHTML diff --git a/modules/blablacar/compat/__init__.py b/modules/blablacar/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/blablacar/compat/weboob_browser_filters_standard.py b/modules/blablacar/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/blablacar/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/blablacar/pages.py b/modules/blablacar/pages.py index 74a80790e0..fb05fd303d 100644 --- a/modules/blablacar/pages.py +++ b/modules/blablacar/pages.py @@ -18,7 +18,7 @@ # along with this weboob module. If not, see . from weboob.capabilities.travel import Departure -from weboob.browser.filters.standard import CleanText, Regexp, CleanDecimal +from .compat.weboob_browser_filters_standard import CleanText, Regexp, CleanDecimal from weboob.browser.filters.html import Link from weboob.browser.elements import ListElement, ItemElement, method from weboob.browser.pages import JsonPage diff --git a/modules/blogspot/compat/__init__.py b/modules/blogspot/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/blogspot/compat/weboob_browser_filters_standard.py b/modules/blogspot/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/blogspot/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/blogspot/pages.py b/modules/blogspot/pages.py index fe95e565dc..e44394632c 100644 --- a/modules/blogspot/pages.py +++ b/modules/blogspot/pages.py @@ -26,7 +26,7 @@ from weboob.browser.pages import HTMLPage, RawPage from weboob.browser.elements import ItemElement, method -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.capabilities.messages import Message diff --git a/modules/bnpcards/compat/__init__.py b/modules/bnpcards/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bnpcards/compat/weboob_browser_filters_standard.py b/modules/bnpcards/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bnpcards/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bnpcards/corporate/compat/__init__.py b/modules/bnpcards/corporate/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bnpcards/corporate/compat/weboob_browser_filters_standard.py b/modules/bnpcards/corporate/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bnpcards/corporate/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bnpcards/corporate/pages.py b/modules/bnpcards/corporate/pages.py index 791034e86d..3134affe0b 100644 --- a/modules/bnpcards/corporate/pages.py +++ b/modules/bnpcards/corporate/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, pagination, NextPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Field, Format +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Field, Format from weboob.browser.filters.html import Link, Attr from weboob.capabilities.bank import Account from weboob.tools.capabilities.bank.transactions import FrenchTransaction diff --git a/modules/bnpcards/pages.py b/modules/bnpcards/pages.py index 5434f42c81..c749db9ff8 100644 --- a/modules/bnpcards/pages.py +++ b/modules/bnpcards/pages.py @@ -24,7 +24,7 @@ from weboob.exceptions import BrowserPasswordExpired from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Field, Env, Format +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Field, Env, Format from weboob.browser.filters.html import Link, Attr, AbsoluteLink from weboob.capabilities.bank import Account from weboob.tools.capabilities.bank.transactions import FrenchTransaction diff --git a/modules/bnporc/enterprise/compat/weboob_browser_filters_standard.py b/modules/bnporc/enterprise/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bnporc/enterprise/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bnporc/enterprise/pages.py b/modules/bnporc/enterprise/pages.py index 27206674b1..ed0d806cea 100644 --- a/modules/bnporc/enterprise/pages.py +++ b/modules/bnporc/enterprise/pages.py @@ -28,7 +28,7 @@ from weboob.browser.filters.json import Dict from weboob.browser.filters.html import TableCell, Attr from weboob.browser.elements import DictElement, ItemElement, method, TableElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Date, Regexp, Format, Eval, BrowserURL, Field, Async, Currency, ) diff --git a/modules/bnporc/pp/compat/weboob_browser_filters_standard.py b/modules/bnporc/pp/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bnporc/pp/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bnporc/pp/pages.py b/modules/bnporc/pp/pages.py index 182d600b82..d52dcd4602 100644 --- a/modules/bnporc/pp/pages.py +++ b/modules/bnporc/pp/pages.py @@ -29,7 +29,7 @@ from weboob.browser.elements import DictElement, ListElement, TableElement, ItemElement, method from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import Format, Eval, Regexp, CleanText, Date, CleanDecimal, Field +from .compat.weboob_browser_filters_standard import Format, Eval, Regexp, CleanText, Date, CleanDecimal, Field from weboob.browser.filters.html import TableCell from weboob.browser.pages import JsonPage, LoggedPage, HTMLPage from weboob.capabilities import NotAvailable @@ -610,10 +610,15 @@ def iter_investments(self): class LifeInsurancesHistoryPage(BNPPage): + IGNORED_STATUSES = ( + 'En cours', + 'Sans suite', + ) + def iter_history(self, coming): for op in self.get('data.listerMouvements.listeMouvements') or []: #We have not date for this statut so we just skit it - if op.get('statut') == u'En cours': + if op.get('statut') in self.IGNORED_STATUSES: continue tr = Transaction.from_dict({ @@ -622,14 +627,16 @@ def iter_history(self, coming): 'amount': op.get('montantNet'), }) - if op.get('statut') == 'Sans suite': - continue - 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: + if op.get('rib', {}).get('codeBanque') == 'null': + self.logger.info('ignoring non-transaction with label %r', tr.raw) + continue + if (op.get('statut') == u'Traité') ^ coming: yield tr @@ -831,6 +838,7 @@ def on_load(self): raise AddRecipientBankError(message=self.get('message')) def get_recipient(self, recipient): + # handle polling response r = Recipient() r.iban = recipient.iban r.id = self.get('data.gestionBeneficiaire.identifiantBeneficiaire') @@ -840,6 +848,7 @@ def get_recipient(self, recipient): r.currency = u'EUR' r.bank_name = NotAvailable r._id_transaction = self.get('data.gestionBeneficiaire.idTransactionAF') or NotAvailable + r._transfer_id = self.get('data.gestionBeneficiaire.identifiantBeneficiaire') or NotAvailable return r diff --git a/modules/bnppere/compat/__init__.py b/modules/bnppere/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bnppere/compat/weboob_browser_filters_standard.py b/modules/bnppere/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bnppere/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bnppere/pages.py b/modules/bnppere/pages.py index 15f1e5a7fa..a09f110a52 100644 --- a/modules/bnppere/pages.py +++ b/modules/bnppere/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, ItemElement, ListElement -from weboob.browser.filters.standard import CleanText, CleanDecimal, Format, Currency, Date, NumberFormatError +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Format, Currency, Date, NumberFormatError from weboob.capabilities.bank import Account, Transaction from weboob.browser.filters.html import Attr from weboob.capabilities.profile import Profile diff --git a/modules/bolden/browser.py b/modules/bolden/browser.py index aac62cf91d..853571165a 100644 --- a/modules/bolden/browser.py +++ b/modules/bolden/browser.py @@ -97,6 +97,10 @@ def iter_documents(self): doc.id = inv.id doc.url = inv._docurl doc.label = 'Contrat %s' % inv.label - doc.type = DocumentTypes.OTHER + doc.type = DocumentTypes.CONTRACT doc.format = 'pdf' yield doc + + self.profile.go() + for doc in self.page.iter_documents(): + yield doc diff --git a/modules/bolden/compat/__init__.py b/modules/bolden/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bolden/compat/weboob_browser_filters_standard.py b/modules/bolden/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bolden/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bolden/module.py b/modules/bolden/module.py index bb3901bc31..ad76ffaf7f 100644 --- a/modules/bolden/module.py +++ b/modules/bolden/module.py @@ -19,7 +19,6 @@ from __future__ import unicode_literals - from weboob.tools.backend import Module, BackendConfig from weboob.tools.value import ValueBackendPassword from weboob.capabilities.bank import CapBankWealth, Account diff --git a/modules/bolden/pages.py b/modules/bolden/pages.py index a9db44b4ce..7564f5909f 100644 --- a/modules/bolden/pages.py +++ b/modules/bolden/pages.py @@ -20,14 +20,15 @@ from __future__ import unicode_literals from weboob.browser.elements import ListElement, ItemElement, method, TableElement -from weboob.browser.filters.html import TableCell, Link, Attr -from weboob.browser.filters.standard import ( - CleanText, CleanDecimal, Slugify, Date, Field, Format, +from weboob.browser.filters.html import TableCell, Link, Attr, AbsoluteLink +from .compat.weboob_browser_filters_standard import ( + CleanText, CleanDecimal, Slugify, Date, Field, Format, Regexp, ) from weboob.browser.pages import HTMLPage, LoggedPage from weboob.capabilities.base import NotAvailable from weboob.capabilities.bank import Account, Transaction, Investment from weboob.capabilities.profile import Profile +from weboob.capabilities.bill import Document, DocumentTypes from weboob.exceptions import BrowserIncorrectPassword from weboob.tools.compat import urljoin @@ -143,3 +144,17 @@ class get_profile(ItemElement): Attr('//input[@id="SubModel_Address_City"]', 'value'), CleanText('//select[@id="SubModel_Address_Country"]/option[@selected]'), ) + + @method + class iter_documents(ListElement): + item_xpath = '//a[starts-with(@href, "/Upload/Show")]' + + class item(ItemElement): + klass = Document + + obj_label = 'Imprimé fiscal unique' + obj_type = DocumentTypes.REPORT + obj_format = 'pdf' + + obj_url = AbsoluteLink('.') + obj_id = Regexp(Field('url'), r'fileId=(\d+)') diff --git a/modules/boursorama/compat/weboob_browser_filters_standard.py b/modules/boursorama/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/boursorama/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/boursorama/module.py b/modules/boursorama/module.py index a2201074e3..29d355e005 100644 --- a/modules/boursorama/module.py +++ b/modules/boursorama/module.py @@ -103,6 +103,9 @@ def transfer_check_label(self, old, new): # Else: inside '<>' chars are deleted old = re.sub(r'<[^>]*>', '', old).strip() old = old.split('<')[0] + + # replace � by ?, like the bank does + old = old.replace('\ufffd', '?') return super(BoursoramaModule, self).transfer_check_label(old, new) def iter_currencies(self): diff --git a/modules/boursorama/pages.py b/modules/boursorama/pages.py index 27e32b356d..9503920c9d 100644 --- a/modules/boursorama/pages.py +++ b/modules/boursorama/pages.py @@ -28,10 +28,10 @@ from weboob.browser.pages import HTMLPage, LoggedPage, pagination, NextPage, FormNotFound, PartialHTMLPage, LoginPage, CsvPage, RawPage, JsonPage from weboob.browser.elements import ListElement, ItemElement, method, TableElement, SkipItem, DictElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Field, Format, Regexp, Date, AsyncLoad, Async, Eval, Env, - Currency as CleanCurrency, Map, + Currency as CleanCurrency, Map, Coalesce, ) from weboob.browser.filters.json import Dict from weboob.browser.filters.html import Attr, Link, TableCell @@ -214,26 +214,28 @@ def is_here(self): # This id appears when there are no accounts (pro and pp) return not self.doc.xpath('//div[contains(@id, "alert-random")]') - ACCOUNT_TYPES = {u'comptes courants': Account.TYPE_CHECKING, - u'cav': Account.TYPE_CHECKING, - 'livret': Account.TYPE_SAVINGS, - 'pel': Account.TYPE_SAVINGS, - 'cel': Account.TYPE_SAVINGS, - u'comptes épargne': Account.TYPE_SAVINGS, - u'mon épargne': Account.TYPE_SAVINGS, - 'csljeune': Account.TYPE_SAVINGS, # in url - u'ord': Account.TYPE_MARKET, - u'comptes bourse': Account.TYPE_MARKET, - u'mes placements financiers': Account.TYPE_MARKET, - u'av': Account.TYPE_LIFE_INSURANCE, - u'assurances vie': Account.TYPE_LIFE_INSURANCE, - u'assurance-vie': Account.TYPE_LIFE_INSURANCE, - u'mes crédits': Account.TYPE_LOAN, - u'crédit': Account.TYPE_LOAN, - u'prêt': Account.TYPE_LOAN, - u'pea': Account.TYPE_PEA, - 'carte': Account.TYPE_CARD, - } + ACCOUNT_TYPES = { + 'comptes courants': Account.TYPE_CHECKING, + 'cav': Account.TYPE_CHECKING, + 'livret': Account.TYPE_SAVINGS, + 'pel': Account.TYPE_SAVINGS, + 'cel': Account.TYPE_SAVINGS, + 'ldd': Account.TYPE_SAVINGS, + 'comptes épargne': Account.TYPE_SAVINGS, + 'mon épargne': Account.TYPE_SAVINGS, + 'csljeune': Account.TYPE_SAVINGS, # in url + 'ord': Account.TYPE_MARKET, + 'comptes bourse': Account.TYPE_MARKET, + 'mes placements financiers': Account.TYPE_MARKET, + 'av': Account.TYPE_LIFE_INSURANCE, + 'assurances vie': Account.TYPE_LIFE_INSURANCE, + 'assurance-vie': Account.TYPE_LIFE_INSURANCE, + 'mes crédits': Account.TYPE_LOAN, + 'crédit': Account.TYPE_LOAN, + 'prêt': Account.TYPE_LOAN, + 'pea': Account.TYPE_PEA, + 'carte': Account.TYPE_CARD, + } @method class iter_accounts(ListElement): @@ -419,12 +421,19 @@ class iter_history(ListElement): class item(ItemElement): klass = Transaction - obj_raw = Transaction.Raw(CleanText('.//div[has-class("list__movement__line--label__name")]')) obj_date = Date(Attr('.//time', 'datetime')) obj_amount = CleanDecimal('.//div[has-class("list__movement__line--amount")]', replace_dots=True) obj_category = CleanText('.//span[has-class("category")]') obj__account_name = CleanText('.//span[contains(@class, "account__name-xs")]', default=None) + # div "label__name" contain two span: one with the short label (hidden in the website) and one with + # the long label. We try to get the long one. If it's empty, we take the content of "label__name" to + # be sure to have a value. + obj_raw = Coalesce( + Transaction.Raw(CleanText('.//span[has-class("list__movement--label-long")]')), + Transaction.Raw(CleanText('.//div[has-class("list__movement__line--label__name")]')), + ) + def obj_id(self): return Attr('.', 'data-id', default=NotAvailable)(self) or Attr('.', 'data-custom-id', default=NotAvailable)(self) @@ -505,6 +514,7 @@ class item(ItemElement): obj_raw = Transaction.Raw(Dict('label')) obj_date = Date(Dict('dateVal'), dayfirst=True) + obj_bdate = Date(Dict('dateOp'), dayfirst=True) obj__account_label = Dict('accountLabel') obj__is_coming = False @@ -853,10 +863,10 @@ def obj_label(self): return label.rstrip('-').rstrip() def obj_category(self): - text = CleanText('./ancestor::div[has-class("deploy--item")]//a[has-class("deploy__title")]')(self) - if 'Mes comptes Boursorama Banque' in text: + text = CleanText('./ancestor::div[has-class("deploy--item")]//a[has-class("deploy__title")]')(self).lower() + if 'mes comptes boursorama banque' in text: return 'Interne' - elif any(exp in text for exp in ('Comptes externes', 'Comptes de tiers', 'Mes bénéficiaires')): + elif any(exp in text for exp in ('comptes externes', 'comptes de tiers', 'mes bénéficiaires')): return 'Externe' def obj_iban(self): diff --git a/modules/bouygues/compat/__init__.py b/modules/bouygues/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bouygues/compat/weboob_browser_filters_standard.py b/modules/bouygues/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bouygues/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bouygues/pages.py b/modules/bouygues/pages.py index ddfe94cd0e..d2a6d76c06 100644 --- a/modules/bouygues/pages.py +++ b/modules/bouygues/pages.py @@ -29,7 +29,7 @@ from weboob.capabilities.profile import Profile from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage, PDFPage from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanDecimal, CleanText, Env, Format, Regexp +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Env, Format, Regexp from weboob.browser.elements import DictElement, ItemElement, method diff --git a/modules/bp/browser.py b/modules/bp/browser.py index a9b296dedb..e075b7c4b6 100644 --- a/modules/bp/browser.py +++ b/modules/bp/browser.py @@ -54,11 +54,12 @@ class BPBrowser(LoginBrowser, StatesMixin): # FIXME beware that '.*' in start of URL() won't match all domains but only under BASEURL + login_image = URL(r'.*wsost/OstBrokerWeb/loginform\?imgid=', UselessPage) login_page = URL(r'.*wsost/OstBrokerWeb/loginform.*', LoginPage) repositionner_chemin_courant = URL(r'.*authentification/repositionnerCheminCourant-identif.ea', repositionnerCheminCourant) init_ident = URL(r'.*authentification/initialiser-identif.ea', Initident) check_password = URL(r'.*authentification/verifierMotDePasse-identif.ea', - r'/voscomptes/canalXHTML/securite/authentification/verifierPresenceCompteOK-identif.ea', + r'/securite/authentification/verifierPresenceCompteOK-identif.ea', r'.*//voscomptes/identification/motdepasse.jsp', CheckPassword) diff --git a/modules/bp/pages/accounthistory.py b/modules/bp/pages/accounthistory.py index 67ca55b739..83238a9d91 100644 --- a/modules/bp/pages/accounthistory.py +++ b/modules/bp/pages/accounthistory.py @@ -29,7 +29,7 @@ from weboob.browser.pages import LoggedPage from weboob.browser.elements import TableElement, ItemElement, method from weboob.browser.filters.html import Link, TableCell -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanDecimal, CleanText, Eval, Field, Async, AsyncLoad, Date, Env, Format, Regexp, ) diff --git a/modules/bp/pages/accountlist.py b/modules/bp/pages/accountlist.py index 351bd2aea3..55fd793a4e 100644 --- a/modules/bp/pages/accountlist.py +++ b/modules/bp/pages/accountlist.py @@ -30,7 +30,7 @@ from weboob.browser.elements import ListElement, ItemElement, method, TableElement from weboob.browser.pages import LoggedPage, RawPage, PartialHTMLPage, HTMLPage from weboob.browser.filters.html import Link, TableCell, Attr -from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, Env, Field, Currency, Async, Date, Format +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Regexp, Env, Field, Currency, Async, Date, Format from weboob.exceptions import BrowserUnavailable from weboob.tools.compat import urljoin, unicode @@ -455,7 +455,7 @@ def on_load(self): self.get_form(id='autoSubmit').submit() -class UselessPage(LoggedPage, HTMLPage): +class UselessPage(LoggedPage, RawPage): pass diff --git a/modules/bp/pages/compat/weboob_browser_filters_standard.py b/modules/bp/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bp/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bp/pages/login.py b/modules/bp/pages/login.py index 0f2bbdd5b5..cf339e0dd0 100644 --- a/modules/bp/pages/login.py +++ b/modules/bp/pages/login.py @@ -23,7 +23,7 @@ from weboob.exceptions import BrowserUnavailable, BrowserIncorrectPassword, NoAccountsException from weboob.browser.pages import LoggedPage -from weboob.browser.filters.standard import CleanText, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Regexp from .compat.weboob_tools_captcha_virtkeyboard import VirtKeyboard from .base import MyHTMLPage diff --git a/modules/bp/pages/mandate.py b/modules/bp/pages/mandate.py index 84eeca9bee..5c9976ec63 100644 --- a/modules/bp/pages/mandate.py +++ b/modules/bp/pages/mandate.py @@ -23,7 +23,7 @@ from weboob.browser.pages import LoggedPage, HTMLPage, pagination from weboob.browser.elements import TableElement, ItemElement, method from weboob.browser.filters.html import Link, Attr, TableCell -from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, \ +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Regexp, \ Format, Currency from weboob.capabilities.base import NotAvailable from weboob.capabilities.bank import Account, Investment diff --git a/modules/bp/pages/pro.py b/modules/bp/pages/pro.py index f80e4a9b68..e9cd4d1d87 100644 --- a/modules/bp/pages/pro.py +++ b/modules/bp/pages/pro.py @@ -21,7 +21,7 @@ from decimal import Decimal from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Date +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Date from weboob.browser.filters.html import Link from weboob.browser.pages import LoggedPage, pagination from weboob.capabilities.bank import Account diff --git a/modules/bp/pages/subscription.py b/modules/bp/pages/subscription.py index f97b9d1a88..c51140b51e 100644 --- a/modules/bp/pages/subscription.py +++ b/modules/bp/pages/subscription.py @@ -23,7 +23,7 @@ from weboob.capabilities.bill import DocumentTypes, Subscription, Document from weboob.browser.pages import LoggedPage, HTMLPage -from weboob.browser.filters.standard import CleanText, Regexp, Env, Date, Format, Field +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env, Date, Format, Field from weboob.browser.filters.html import Link, Attr, TableCell from weboob.browser.elements import ListElement, ItemElement, method, TableElement diff --git a/modules/bp/pages/transfer.py b/modules/bp/pages/transfer.py index 8d71ee1924..185dde5e72 100644 --- a/modules/bp/pages/transfer.py +++ b/modules/bp/pages/transfer.py @@ -26,7 +26,7 @@ ) from weboob.capabilities.base import find_object from weboob.browser.pages import LoggedPage -from weboob.browser.filters.standard import CleanText, Env, Regexp, Date, CleanDecimal +from .compat.weboob_browser_filters_standard import CleanText, Env, Regexp, Date, CleanDecimal from weboob.browser.filters.html import Attr, Link from weboob.browser.elements import ListElement, ItemElement, method, SkipItem from weboob.tools.capabilities.bank.transactions import FrenchTransaction diff --git a/modules/bred/bred/compat/__init__.py b/modules/bred/bred/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bred/bred/compat/weboob_browser_filters_standard.py b/modules/bred/bred/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bred/bred/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bred/bred/pages.py b/modules/bred/bred/pages.py index e2a5b719dc..03536f12d5 100644 --- a/modules/bred/bred/pages.py +++ b/modules/bred/bred/pages.py @@ -31,7 +31,7 @@ from weboob.capabilities.bank import Account, Investment from weboob.tools.capabilities.bank.investments import is_isin_valid from weboob.capabilities.profile import Person -from weboob.browser.filters.standard import CleanText, CleanDecimal, Env, Eval +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Env, Eval from weboob.browser.filters.json import Dict from weboob.browser.elements import DictElement, ItemElement, method from weboob.tools.capabilities.bank.transactions import FrenchTransaction diff --git a/modules/bred/dispobank/compat/__init__.py b/modules/bred/dispobank/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/bred/dispobank/compat/weboob_browser_filters_standard.py b/modules/bred/dispobank/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/bred/dispobank/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/bred/dispobank/pages.py b/modules/bred/dispobank/pages.py index ce7c88cabb..a070bd8b25 100644 --- a/modules/bred/dispobank/pages.py +++ b/modules/bred/dispobank/pages.py @@ -24,7 +24,7 @@ from collections import OrderedDict from weboob.browser.pages import LoggedPage, HTMLPage, RawPage, FormNotFound -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.tools.misc import to_unicode from weboob.capabilities.bank import Account from weboob.capabilities.profile import Profile diff --git a/modules/btmon/compat/__init__.py b/modules/btmon/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/btmon/compat/weboob_browser_filters_standard.py b/modules/btmon/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/btmon/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/btmon/pages.py b/modules/btmon/pages.py index aaa74b64f8..1e068e9d52 100644 --- a/modules/btmon/pages.py +++ b/modules/btmon/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage, pagination -from weboob.browser.filters.standard import Regexp, CleanText, CleanDecimal, Format +from .compat.weboob_browser_filters_standard import Regexp, CleanText, CleanDecimal, Format from weboob.browser.filters.html import AbsoluteLink diff --git a/modules/caels/compat/__init__.py b/modules/caels/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/caels/compat/weboob_browser_filters_standard.py b/modules/caels/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/caels/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/caels/pages.py b/modules/caels/pages.py index 67cc5a7064..cf98b59cbd 100644 --- a/modules/caels/pages.py +++ b/modules/caels/pages.py @@ -19,7 +19,7 @@ from weboob.browser.elements import ItemElement, method, DictElement -from weboob.browser.filters.standard import CleanDecimal, Date, Field, Env +from .compat.weboob_browser_filters_standard import CleanDecimal, Date, Field, Env from weboob.browser.filters.json import Dict from weboob.browser.pages import AbstractPage from weboob.capabilities.bank import Investment diff --git a/modules/caissedepargne/cenet/browser.py b/modules/caissedepargne/cenet/browser.py index 2905abfe42..4df46b8cda 100644 --- a/modules/caissedepargne/cenet/browser.py +++ b/modules/caissedepargne/cenet/browser.py @@ -185,8 +185,10 @@ def get_history(self, account): if tr.type is FrenchTransaction.TYPE_CARD_SUMMARY: if find_object(card_tr_list, label=tr.label, amount=tr.amount, raw=tr.raw, date=tr.date, rdate=tr.rdate): - self.logger.warning('Duplicate transaction: %s' % tr) + self.logger.warning('Duplicated transaction: %s', tr) + items.pop() continue + card_tr_list.append(tr) tr.deleted = True tr_dict = [tr_dict for tr_dict in data_out if tr_dict['Libelle'] == tr.label] diff --git a/modules/caissedepargne/cenet/compat/__init__.py b/modules/caissedepargne/cenet/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/caissedepargne/cenet/compat/weboob_browser_filters_standard.py b/modules/caissedepargne/cenet/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/caissedepargne/cenet/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/caissedepargne/cenet/pages.py b/modules/caissedepargne/cenet/pages.py index 15f44efc2a..d01099ec52 100644 --- a/modules/caissedepargne/cenet/pages.py +++ b/modules/caissedepargne/cenet/pages.py @@ -23,10 +23,10 @@ from weboob.browser.pages import LoggedPage, HTMLPage, JsonPage from weboob.browser.elements import DictElement, ItemElement, method -from weboob.browser.filters.standard import Date, CleanDecimal, CleanText, Format, Field, Env, Regexp, Currency +from .compat.weboob_browser_filters_standard import Date, CleanDecimal, CleanText, Format, Field, Env, Regexp, Currency from weboob.browser.filters.json import Dict from weboob.capabilities import NotAvailable -from weboob.capabilities.bank import Account, Transaction, Loan +from weboob.capabilities.bank import Account, Loan from weboob.capabilities.contact import Advisor from weboob.capabilities.profile import Profile from weboob.capabilities.bill import DocumentTypes, Subscription, Document @@ -34,6 +34,39 @@ from weboob.exceptions import BrowserUnavailable +class Transaction(FrenchTransaction): + PATTERNS = [(re.compile('^CB (?P.*?) FACT (?P
\d{2})(?P\d{2})(?P\d{2})', re.IGNORECASE), + FrenchTransaction.TYPE_CARD), + (re.compile('^RET(RAIT)? DAB (?P
\d+)-(?P\d+)-.*', re.IGNORECASE), + FrenchTransaction.TYPE_WITHDRAWAL), + (re.compile('^RET(RAIT)? DAB (?P.*?) (?P
\d{2})(?P\d{2})(?P\d{2}) (?P\d{2})H(?P\d{2})', re.IGNORECASE), + FrenchTransaction.TYPE_WITHDRAWAL), + (re.compile('^VIR(EMENT)?(\.PERIODIQUE)? (?P.*)', re.IGNORECASE), + FrenchTransaction.TYPE_TRANSFER), + (re.compile('^PRLV (?P.*)', re.IGNORECASE), + FrenchTransaction.TYPE_ORDER), + (re.compile('^CHEQUE.*', re.IGNORECASE), FrenchTransaction.TYPE_CHECK), + (re.compile('^(CONVENTION \d+ )?COTIS(ATION)? (?P.*)', re.IGNORECASE), + FrenchTransaction.TYPE_BANK), + (re.compile(r'^\* (?P.*)', re.IGNORECASE), + FrenchTransaction.TYPE_BANK), + (re.compile('^REMISE (?P.*)', re.IGNORECASE), + FrenchTransaction.TYPE_DEPOSIT), + (re.compile('^(?P.*)( \d+)? QUITTANCE .*', re.IGNORECASE), + FrenchTransaction.TYPE_ORDER), + (re.compile('^CB [\d\*]+ TOT DIF .*', re.IGNORECASE), + FrenchTransaction.TYPE_CARD_SUMMARY), + (re.compile('^CB [\d\*]+ (?P.*)', re.IGNORECASE), + FrenchTransaction.TYPE_CARD), + (re.compile('^CB (?P.*?) (?P
\d{2})(?P\d{2})(?P\d{2})', re.IGNORECASE), + FrenchTransaction.TYPE_CARD), + (re.compile('\*CB (?P.*?) (?P
\d{2})(?P\d{2})(?P\d{2})', re.IGNORECASE), + FrenchTransaction.TYPE_CARD), + (re.compile('^FAC CB (?P.*?) (?P
\d{2})/(?P\d{2})', re.IGNORECASE), + FrenchTransaction.TYPE_CARD), + ] + + class LoginPage(JsonPage): def get_response(self): return self.doc @@ -187,14 +220,12 @@ class CenetAccountHistoryPage(LoggedPage, CenetJsonPage): 'CHEQUE': Transaction.TYPE_CHECK, 'REMISE CHEQUE': Transaction.TYPE_CASH_DEPOSIT, 'PRLV': Transaction.TYPE_ORDER, - 'CB': Transaction.TYPE_CARD } TR_TYPES_API = { 'VIR': Transaction.TYPE_TRANSFER, 'PE': Transaction.TYPE_ORDER, # PRLV 'CE': Transaction.TYPE_CHECK, # CHEQUE - 'CB': Transaction.TYPE_CARD, 'DE': Transaction.TYPE_CASH_DEPOSIT, # APPRO 'PI': Transaction.TYPE_CASH_DEPOSIT, # REMISE CHEQUE } @@ -291,39 +322,6 @@ def on_load(self): raise BrowserUnavailable(CleanText('//div[@id="message_error_hs"]')(self.doc)) -class Transaction(FrenchTransaction): - PATTERNS = [(re.compile('^CB (?P.*?) FACT (?P
\d{2})(?P\d{2})(?P\d{2})', re.IGNORECASE), - FrenchTransaction.TYPE_CARD), - (re.compile('^RET(RAIT)? DAB (?P
\d+)-(?P\d+)-.*', re.IGNORECASE), - FrenchTransaction.TYPE_WITHDRAWAL), - (re.compile('^RET(RAIT)? DAB (?P.*?) (?P
\d{2})(?P\d{2})(?P\d{2}) (?P\d{2})H(?P\d{2})', re.IGNORECASE), - FrenchTransaction.TYPE_WITHDRAWAL), - (re.compile('^VIR(EMENT)?(\.PERIODIQUE)? (?P.*)', re.IGNORECASE), - FrenchTransaction.TYPE_TRANSFER), - (re.compile('^PRLV (?P.*)', re.IGNORECASE), - FrenchTransaction.TYPE_ORDER), - (re.compile('^CHEQUE.*', re.IGNORECASE), FrenchTransaction.TYPE_CHECK), - (re.compile('^(CONVENTION \d+ )?COTIS(ATION)? (?P.*)', re.IGNORECASE), - FrenchTransaction.TYPE_BANK), - (re.compile(r'^\* (?P.*)', re.IGNORECASE), - FrenchTransaction.TYPE_BANK), - (re.compile('^REMISE (?P.*)', re.IGNORECASE), - FrenchTransaction.TYPE_DEPOSIT), - (re.compile('^(?P.*)( \d+)? QUITTANCE .*', re.IGNORECASE), - FrenchTransaction.TYPE_ORDER), - (re.compile('^CB [\d\*]+ TOT DIF .*', re.IGNORECASE), - FrenchTransaction.TYPE_CARD_SUMMARY), - (re.compile('^CB [\d\*]+ (?P.*)', re.IGNORECASE), - FrenchTransaction.TYPE_CARD), - (re.compile('^CB (?P.*?) (?P
\d{2})(?P\d{2})(?P\d{2})', re.IGNORECASE), - FrenchTransaction.TYPE_CARD), - (re.compile('\*CB (?P.*?) (?P
\d{2})(?P\d{2})(?P\d{2})', re.IGNORECASE), - FrenchTransaction.TYPE_CARD), - (re.compile('^FAC CB (?P.*?) (?P
\d{2})/(?P\d{2})', re.IGNORECASE), - FrenchTransaction.TYPE_CARD), - ] - - class SubscriptionPage(LoggedPage, CenetJsonPage): @method class iter_subscription(DictElement): diff --git a/modules/caissedepargne/compat/weboob_browser_filters_standard.py b/modules/caissedepargne/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/caissedepargne/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/caissedepargne/pages.py b/modules/caissedepargne/pages.py index 01789ae4cb..541feea84f 100644 --- a/modules/caissedepargne/pages.py +++ b/modules/caissedepargne/pages.py @@ -30,7 +30,7 @@ from weboob.browser.pages import LoggedPage, HTMLPage, JsonPage, pagination, FormNotFound from weboob.browser.elements import ItemElement, method, ListElement, TableElement, SkipItem, DictElement -from weboob.browser.filters.standard import Date, CleanDecimal, Regexp, CleanText, Env, Upper, Field, Eval, Format, Currency +from .compat.weboob_browser_filters_standard import Date, CleanDecimal, Regexp, CleanText, Env, Upper, Field, Eval, Format, Currency from weboob.browser.filters.html import Link, Attr, TableCell from weboob.capabilities import NotAvailable from weboob.capabilities.bank import ( @@ -591,9 +591,12 @@ def go_loan_list(self): def is_history_of(self, account_id): """ - Check whether the displayed history is for the correct account + Check whether the displayed history is for the correct account. + If we do not find the select box we consider we are on the expected account (like it was before this check) """ - return bool(self.doc.xpath('//option[@value="%s" and @selected]' % account_id)) + if self.doc.xpath('//select[@id="MM_HISTORIQUE_COMPTE_m_ExDropDownList"]'): + return bool(self.doc.xpath('//option[@value="%s" and @selected]' % account_id)) + return True def go_history(self, info, is_cbtab=False): form = self.get_form(id='main') diff --git a/modules/carrefourbanque/compat/__init__.py b/modules/carrefourbanque/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/carrefourbanque/compat/weboob_browser_filters_standard.py b/modules/carrefourbanque/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/carrefourbanque/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/carrefourbanque/pages.py b/modules/carrefourbanque/pages.py index cca52b6d06..409ce32cb1 100644 --- a/modules/carrefourbanque/pages.py +++ b/modules/carrefourbanque/pages.py @@ -26,7 +26,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, TableElement, ItemElement, method -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( Regexp, Field, CleanText, CleanDecimal, Eval, Currency ) from weboob.browser.filters.html import Link, TableCell, Attr, AttributeNotFound diff --git a/modules/cci/compat/__init__.py b/modules/cci/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cci/compat/weboob_browser_filters_standard.py b/modules/cci/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cci/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cci/pages.py b/modules/cci/pages.py index da9752d265..fbda8b46bf 100644 --- a/modules/cci/pages.py +++ b/modules/cci/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, TableElement, method -from weboob.browser.filters.standard import Filter, CleanText, Format, Env, DateTime, Join +from .compat.weboob_browser_filters_standard import Filter, CleanText, Format, Env, DateTime, Join from weboob.browser.filters.html import Link, CleanHTML, TableCell from weboob.capabilities.job import BaseJobAdvert diff --git a/modules/centquatre/compat/__init__.py b/modules/centquatre/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/centquatre/compat/weboob_browser_filters_standard.py b/modules/centquatre/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/centquatre/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/centquatre/pages.py b/modules/centquatre/pages.py index f05bbfdbeb..2bec02b92c 100644 --- a/modules/centquatre/pages.py +++ b/modules/centquatre/pages.py @@ -20,8 +20,8 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, ItemElement, ListElement -from weboob.browser.filters.standard import CleanDecimal, CleanText -from weboob.browser.filters.standard import DateTime, Env, Eval, Format +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText +from .compat.weboob_browser_filters_standard import DateTime, Env, Eval, Format from weboob.browser.filters.html import Link from weboob.capabilities.calendar import CATEGORIES, TICKET diff --git a/modules/chronopost/compat/__init__.py b/modules/chronopost/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/chronopost/compat/weboob_browser_filters_standard.py b/modules/chronopost/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/chronopost/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/chronopost/pages.py b/modules/chronopost/pages.py index 270c342443..33d3027474 100644 --- a/modules/chronopost/pages.py +++ b/modules/chronopost/pages.py @@ -22,7 +22,7 @@ from weboob.capabilities import NotAvailable from weboob.browser.pages import JsonPage, HTMLPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Env, CleanText, DateTime +from .compat.weboob_browser_filters_standard import Env, CleanText, DateTime from weboob.tools.date import parse_french_date diff --git a/modules/cityscoot/compat/__init__.py b/modules/cityscoot/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cityscoot/compat/weboob_browser_filters_standard.py b/modules/cityscoot/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cityscoot/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cityscoot/pages.py b/modules/cityscoot/pages.py index a80a53be00..e5aee8bd81 100644 --- a/modules/cityscoot/pages.py +++ b/modules/cityscoot/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import ItemElement, TableElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Env, Regexp, Format, Date, Async, AsyncLoad +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Env, Regexp, Format, Date, Async, AsyncLoad from weboob.browser.filters.html import Link from weboob.capabilities.bill import DocumentTypes, Bill, Subscription from weboob.capabilities.base import NotAvailable diff --git a/modules/cmes/compat/__init__.py b/modules/cmes/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cmes/compat/weboob_browser_filters_standard.py b/modules/cmes/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cmes/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cmes/pages.py b/modules/cmes/pages.py index 8b49294943..948eabeda7 100644 --- a/modules/cmes/pages.py +++ b/modules/cmes/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, ItemElement, method, TableElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Upper, Date, Regexp, Field, CleanDecimal, Env, Async, AsyncLoad, Currency, ) diff --git a/modules/cmso/par/compat/__init__.py b/modules/cmso/par/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cmso/par/compat/weboob_browser_filters_standard.py b/modules/cmso/par/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cmso/par/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cmso/par/pages.py b/modules/cmso/par/pages.py index df16bfdc72..8216b0b478 100644 --- a/modules/cmso/par/pages.py +++ b/modules/cmso/par/pages.py @@ -28,7 +28,7 @@ from weboob.browser.pages import HTMLPage, JsonPage, RawPage, LoggedPage, pagination from weboob.browser.elements import DictElement, ItemElement, TableElement, SkipItem, method -from weboob.browser.filters.standard import CleanText, Upper, Date, Regexp, Format, CleanDecimal, Filter, Env, Slugify, Field +from .compat.weboob_browser_filters_standard import CleanText, Upper, Date, Regexp, Format, CleanDecimal, Filter, Env, Slugify, Field from weboob.browser.filters.json import Dict from weboob.browser.filters.html import Attr, Link, TableCell from weboob.browser.exceptions import ServerError @@ -296,7 +296,7 @@ class Transaction(FrenchTransaction): class HistoryPage(LoggedPage, JsonPage): def has_deferred_cards(self): - return Dict('pendingDeferredDebitCardList/currentMonthCardList', default=None) + return Dict('pendingDeferredDebitCardList/currentMonthCardList', default=None)(self.doc) def get_keys(self): if 'exception' in self.doc: diff --git a/modules/cmso/par/transfer_pages.py b/modules/cmso/par/transfer_pages.py index eea18b7def..832310a82a 100644 --- a/modules/cmso/par/transfer_pages.py +++ b/modules/cmso/par/transfer_pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import JsonPage, LoggedPage from weboob.browser.elements import DictElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Currency +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Currency from weboob.browser.filters.json import Dict from weboob.capabilities.bank import Recipient, Transfer, TransferBankError from weboob.capabilities.base import NotAvailable diff --git a/modules/cmso/pro/compat/__init__.py b/modules/cmso/pro/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cmso/pro/compat/weboob_browser_filters_standard.py b/modules/cmso/pro/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cmso/pro/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cmso/pro/pages.py b/modules/cmso/pro/pages.py index 2486b0f930..46127d19c1 100644 --- a/modules/cmso/pro/pages.py +++ b/modules/cmso/pro/pages.py @@ -24,7 +24,7 @@ from weboob.exceptions import BrowserIncorrectPassword from weboob.browser.pages import HTMLPage, JsonPage, pagination from weboob.browser.elements import ListElement, ItemElement, TableElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, DateGuesser, Env, Field, Filter, Regexp, Currency, Date +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, DateGuesser, Env, Field, Filter, Regexp, Currency, Date from weboob.browser.filters.html import Link, Attr, TableCell from weboob.capabilities.bank import Account, Investment from weboob.capabilities.base import NotAvailable diff --git a/modules/colissimo/browser.py b/modules/colissimo/browser.py index 0d227aab30..d92839f719 100644 --- a/modules/colissimo/browser.py +++ b/modules/colissimo/browser.py @@ -18,9 +18,9 @@ # along with this weboob module. If not, see . from weboob.capabilities.parcel import Event, ParcelNotFound -from weboob.browser import PagesBrowser, URL +from weboob.browser.browsers import PagesBrowser, URL from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Date, Eval, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Date, Eval, Regexp from weboob.browser.pages import HTMLPage from weboob.browser.profiles import Firefox diff --git a/modules/colissimo/compat/__init__.py b/modules/colissimo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/colissimo/compat/weboob_browser_filters_standard.py b/modules/colissimo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/colissimo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cpasbien/compat/__init__.py b/modules/cpasbien/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cpasbien/compat/weboob_browser_filters_standard.py b/modules/cpasbien/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cpasbien/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cpasbien/pages.py b/modules/cpasbien/pages.py index 9b0b429ce5..89748dd0e5 100644 --- a/modules/cpasbien/pages.py +++ b/modules/cpasbien/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText, Type, Format +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Type, Format from weboob.browser.filters.html import CleanHTML diff --git a/modules/cragr/api/browser.py b/modules/cragr/api/browser.py index ae6f7118dd..cd76d41361 100644 --- a/modules/cragr/api/browser.py +++ b/modules/cragr/api/browser.py @@ -613,18 +613,18 @@ def iter_transfer_recipients(self, account, transfer_space_info=None): # can't use 'ignore_duplicate' in DictElement because we need the 'index' to do transfer seen = set() - seen.add(account.iban) + seen.add(account.id) for index, internal_rcpt in enumerate(self.page.iter_internal_recipient()): internal_rcpt._index = index - if internal_rcpt._is_recipient and (internal_rcpt.iban not in seen): - seen.add(internal_rcpt.iban) + if internal_rcpt._is_recipient and (internal_rcpt.id not in seen): + seen.add(internal_rcpt.id) yield internal_rcpt for index, external_rcpt in enumerate(self.page.iter_external_recipient()): external_rcpt._index = index - if external_rcpt.iban not in seen: - seen.add(external_rcpt.iban) + if external_rcpt.id not in seen: + seen.add(external_rcpt.id) yield external_rcpt @need_login @@ -664,10 +664,16 @@ def init_transfer(self, transfer, **params): 'transferCurrencyCode': account.currency, 'transferDate': transfer.exec_date.strftime('%d/%m/%Y'), 'transferFrequency': 'U', - 'transferRef': '', + 'transferRef': transfer.label, 'transferType': 'UNIQUE', 'typeCompte': account.label, } + + # update transfer data according to recipient category + if recipient.category == 'Interne': + data['creditAccountNumber'] = recipient.id + data['recipientName'] = recipient._owner_name + # init transfer request self.transfer.go( space=space, diff --git a/modules/cragr/api/compat/weboob_browser_filters_standard.py b/modules/cragr/api/compat/weboob_browser_filters_standard.py index 39f6eaebcd..f382d162f0 100644 --- a/modules/cragr/api/compat/weboob_browser_filters_standard.py +++ b/modules/cragr/api/compat/weboob_browser_filters_standard.py @@ -1,1063 +1,49 @@ -# -*- coding: utf-8 -*- -# Copyright(C) 2014 Romain Bignon -# -# This file is part of weboob. -# -# weboob is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# weboob is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with weboob. If not, see . +import weboob.browser.filters.standard as OLD -from __future__ import absolute_import +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) -import datetime -import re -import unicodedata -from collections import Iterator -from decimal import Decimal, InvalidOperation -from itertools import islice -from dateutil.parser import parse as parse_date - -from weboob.browser.url import URL -from weboob.capabilities.base import Currency as BaseCurrency -from weboob.capabilities.base import empty -from weboob.tools.compat import basestring, long, parse_qs, unicode, urlparse - -from weboob.browser.filters.base import _NO_DEFAULT, Filter, FilterError, ItemNotFound, _Filter, debug - -__all__ = ['FilterError', 'ColumnNotFound', 'RegexpError', 'FormatError', - 'Filter', 'Base', 'Env', 'TableCell', 'RawText', - 'CleanText', 'Lower', 'Upper', 'Capitalize', 'CleanDecimal', - 'Field', 'Regexp', 'Map', 'DateTime', 'Date', 'Time', 'DateGuesser', - 'Duration', 'MultiFilter', 'CombineDate', 'Format', 'Join', 'Type', - 'Eval', 'BrowserURL', 'Async', 'AsyncLoad', - 'QueryValue', 'Coalesce'] - - -from weboob.browser.filters.standard import ColumnNotFound as _ColumnNotFound -class ColumnNotFound(_ColumnNotFound): - pass - - -from weboob.browser.filters.standard import RegexpError as _RegexpError -class RegexpError(_RegexpError): - pass - - -from weboob.browser.filters.standard import FormatError as _FormatError -class FormatError(_FormatError): - pass - - -from weboob.browser.filters.standard import AsyncLoad as _AsyncLoad -class AsyncLoad(_AsyncLoad): - """Load a page asynchronously for later use. - - Often used in combination with :class:`Async` filter. - """ - - def __call__(self, item): - link = self.select(self.selector, item) - return item.page.browser.async_open(link) if link else None - - -from weboob.browser.filters.standard import Async as _Async -class Async(_Async): - """Selector that uses another page fetched earlier. - - Often used in combination with :class:`AsyncLoad` filter. - Requires that the other page's URL is matched with a Page by the Browser. - - Example:: - - class item(ItemElement): - load_details = Field('url') & AsyncLoad - - obj_description = Async('details') & CleanText('//h3') - """ - - def __init__(self, name, selector=None): - super(Async, self).__init__() - self.selector = selector - self.name = name - - def __and__(self, o): - if isinstance(o, type) and issubclass(o, _Filter): - o = o() - self.selector = o - return self - - def __call__(self, item): - if item.loaders[self.name] is None: - return None - - return self.select(self.selector, self.loaded_page(item).doc) - - def filter(self, *args): - raise AttributeError() - - def loaded_page(self, item): - result = item.loaders[self.name].result() - assert result.page is not None, 'The loaded url %s hasn\'t been matched by an URL object' % result.url - return result.page - - -from weboob.browser.filters.standard import Base as _Base -class Base(_Base): - """ - Change the base element used in filters. - - >>> Base(Env('header'), CleanText('./h1')) # doctest: +SKIP - """ - - def __call__(self, item): - base = self.select(self.base, item) - return self.select(self.selector, base) - - def __init__(self, base, selector=None, default=_NO_DEFAULT): - super(Base, self).__init__(selector, default) - self.base = base - - -from weboob.browser.filters.standard import Decode as _Decode -class Decode(_Decode): - """ - Filter that aims to decode urlencoded strings - - >>> Decode(Env('_id')) # doctest: +ELLIPSIS - - >>> from .html import Link - >>> Decode(Link('./a')) # doctest: +ELLIPSIS - - """ - - def __call__(self, item): - self.encoding = item.page.ENCODING if item.page.ENCODING else 'utf-8' - return self.filter(self.select(self.selector, item)) - - @debug() - def filter(self, txt): - try: - try: - from urllib.parse import unquote - txt = unquote(txt, self.encoding) - except ImportError: - from urllib import unquote - txt = unquote(txt.encode('ascii')).decode(self.encoding) - except (UnicodeDecodeError, UnicodeEncodeError): - pass - - return txt - - -from weboob.browser.filters.standard import Env as _Env -class Env(_Env): - """ - Filter to get environment value of the item. - - It is used for example to get page parameters, or when there is a parse() - method on ItemElement. - """ - - def __init__(self, name, default=_NO_DEFAULT): - super(Env, self).__init__(default) - self.name = name - - def __call__(self, item): - try: - return item.env[self.name] - except KeyError: - return self.default_or_raise(ItemNotFound('Environment variable %s not found' % self.name)) - - -from weboob.browser.filters.standard import TableCell as _TableCell -class TableCell(_TableCell): - """ - Used with TableElement, gets the cell element from its name. - - For example: - - >>> from weboob.capabilities.bank import Transaction - >>> from weboob.browser.elements import TableElement, ItemElement - >>> class table(TableElement): - ... head_xpath = '//table/thead/th' - ... item_xpath = '//table/tbody/tr' - ... col_date = u'Date' - ... col_label = [u'Name', u'Label'] - ... class item(ItemElement): - ... klass = Transaction - ... obj_date = Date(TableCell('date')) - ... obj_label = CleanText(TableCell('label')) - ... - - The 'colspan' variable enables the handling of table tags that have - a "colspan" attribute that modify the width of the column: - for example will occupy two columns instead of one, - creating a column shift for all the next columns that must be taken - in consideration when trying to match columns values with column heads. - """ - - def __init__(self, *names, **kwargs): - support_th = kwargs.pop('support_th', False) - self.colspan = kwargs.pop('colspan', False) - super(TableCell, self).__init__(**kwargs) - self.names = names - - if support_th: - self.td = '(./th | ./td)[%s]' - else: - self.td = './td[%s]' - - """ - The two methods below are used to verify that modifying TableCell - to handle colspans does not modify the class behavior in weboob modules. - The "assert" should crash if a module does not return the same results - with and without handling colspans. - """ - - def call_without_colspan(self, item): - # Former behavior without handling colspans > 1 - for name in self.names: - idx = item.parent.get_colnum(name) - if idx is not None: - ret = item.xpath(self.td % (idx + 1)) - for el in ret: - self.highlight_el(el, item) - return ret - return self.default_or_raise(ColumnNotFound('Unable to find column %s' % ' or '.join(self.names))) - - def call_with_colspan(self, item): - # New behavior, handling colspans > 1 - for name in self.names: - col_idx = item.parent.get_colnum(name) - if col_idx is not None: - current_col = 0 - for td_idx in range(col_idx + 1): - ret = item.xpath(self.td % (td_idx + 1)) - if col_idx <= current_col: - for el in ret: - self.highlight_el(el, item) - return ret - - if not ret: - # There might no be no TD at all - # ColumnNotFound seems for case when corresponding header is not found - # Thus for compat return empty - return [] - - current_col += int(ret[0].attrib.get('colspan', 1)) - - return self.default_or_raise(ColumnNotFound('Unable to find column %s' % ' or '.join(self.names))) - - def __call__(self, item): - if self.colspan: - return self.call_with_colspan(item) - - ret_without_colspan = self.call_without_colspan(item) - ret_with_colspan = self.call_with_colspan(item) - assert ret_without_colspan == ret_with_colspan, 'Different behavior with and without colspan in TableCell' - return ret_with_colspan - - -from weboob.browser.filters.standard import RawText as _RawText -class RawText(_RawText): - """Get raw text from an element. - - Unlike :class:`CleanText`, whitespace is kept as is. - """ - - def __init__(self, selector=None, children=False, default=_NO_DEFAULT): - """ - :param children: whether to get text from children elements of the select elements - :type children: bool - """ - - super(RawText, self).__init__(selector, default=default) - self.children = children - - @debug() - def filter(self, el): - if isinstance(el, (tuple, list)): - return u' '.join([self.filter(e) for e in el]) - - if self.children: - text = el.text_content() - else: - text = el.text - - if text is None: - result = self.default - else: - result = unicode(text) - - return result - - -from weboob.browser.filters.standard import CleanText as _CleanText -class CleanText(_CleanText): - """ - Get a cleaned text from an element. - - It first replaces all tabs and multiple spaces - (including newlines if ``newlines`` is True) - to one space and strips the result string. - - The result is coerced into unicode, and optionally normalized - according to the ``normalize`` argument. - - Then it replaces all symbols given in the ``symbols`` argument. - - >>> CleanText().filter('coucou ') == u'coucou' - True - >>> CleanText().filter(u'coucou\xa0coucou') == u'coucou coucou' - True - >>> CleanText(newlines=True).filter(u'coucou\\r\\n coucou ') == u'coucou coucou' - True - >>> CleanText(newlines=False).filter(u'coucou\\r\\n coucou ') == u'coucou\\ncoucou' - True - """ - - def __init__(self, selector=None, symbols='', replace=[], children=True, newlines=True, normalize='NFC', **kwargs): - """ - :param symbols: list of strings to remove from text - :type symbols: list - :param replace: optional pairs of text replacements to perform - :type replace: list[tuple[str, str]] - :param children: whether to get text from children elements of the select elements - :type children: bool - :param newlines: if True, newlines will be converted to space too - :type newlines: bool - :param normalize: Unicode normalization to perform - :type normalize: str or None - """ - - super(CleanText, self).__init__(selector, **kwargs) - self.symbols = symbols - self.toreplace = replace - self.children = children - self.newlines = newlines - self.normalize = normalize - - @debug() - def filter(self, txt): - if isinstance(txt, (tuple, list)): - txt = u' '.join([self.clean(item, children=self.children) for item in txt]) - - txt = self.clean(txt, self.children, self.newlines, self.normalize) - txt = self.remove(txt, self.symbols) - txt = self.replace(txt, self.toreplace) - # ensure it didn't become str by mistake - return unicode(txt) - - @classmethod - def clean(cls, txt, children=True, newlines=True, normalize='NFC'): - if not isinstance(txt, basestring): - if children: - txt = [t.strip() for t in txt.itertext()] - else: - txt = [t.strip() for t in txt.xpath('./text()')] - txt = u' '.join(txt) # 'foo bar' - if newlines: - txt = re.compile(u'\s+', flags=re.UNICODE).sub(u' ', txt) # 'foo bar' - else: - # normalize newlines and clean what is inside - txt = '\n'.join([cls.clean(l) for l in txt.splitlines()]) - txt = txt.strip() - # lxml under Python 2 returns str instead of unicode if it is pure ASCII - txt = unicode(txt) - # normalize to a standard Unicode form - if normalize: - txt = unicodedata.normalize(normalize, txt) - return txt - - @classmethod - def remove(cls, txt, symbols): - for symbol in symbols: - txt = txt.replace(symbol, '') - return txt.strip() - - @classmethod - def replace(cls, txt, replace): - for before, after in replace: - txt = txt.replace(before, after) - return txt - - -from weboob.browser.filters.standard import Lower as _Lower -class Lower(_Lower): - """Extract text with :class:`CleanText` and convert to lower-case.""" - - @debug() - def filter(self, txt): - txt = super(Lower, self).filter(txt) - return txt.lower() - - -from weboob.browser.filters.standard import Upper as _Upper -class Upper(_Upper): - """Extract text with :class:`CleanText` and convert to upper-case.""" - - @debug() - def filter(self, txt): - txt = super(Upper, self).filter(txt) - return txt.upper() - - -from weboob.browser.filters.standard import Capitalize as _Capitalize -class Capitalize(_Capitalize): - """Extract text with :class:`CleanText` and capitalize it.""" - - @debug() - def filter(self, txt): - txt = super(Capitalize, self).filter(txt) - return txt.title() - - -from weboob.browser.filters.standard import Currency as _Currency -class Currency(_Currency): - @debug() - def filter(self, txt): - txt = super(Currency, self).filter(txt) - return BaseCurrency.get_currency(txt) - - -from weboob.browser.filters.standard import NumberFormatError as _NumberFormatError -class NumberFormatError(_NumberFormatError): +try: + __all__ = OLD.__all__ +except AttributeError: pass -from weboob.browser.filters.standard import CleanDecimal as _CleanDecimal -class CleanDecimal(_CleanDecimal): - """ - Get a cleaned Decimal value from an element. - - `replace_dots` is False by default. A dot is interpreted as a decimal separator. - - If `replace_dots` is set to True, we remove all the dots. The ',' is used as decimal - separator (often useful for French values) - - If `replace_dots` is a tuple, the first element will be used as the thousands separator, - and the second as the decimal separator. - - See http://en.wikipedia.org/wiki/Thousands_separator#Examples_of_use - - For example, for the UK style (as in 1,234,567.89): - - >>> CleanDecimal('./td[1]', replace_dots=(',', '.')) # doctest: +SKIP - """ - - def __init__(self, selector=None, replace_dots=False, sign=None, legacy=True, default=_NO_DEFAULT): - """ - :param sign: function accepting the text as param and returning the sign - """ - - super(CleanDecimal, self).__init__(selector, default=default) - self.replace_dots = replace_dots - self.sign = sign - self.legacy = legacy - if not legacy: - thousands_sep, decimal_sep = self.replace_dots - self.matching = re.compile(r'([+-]?)\s*(\d[\d%s%s]*|%s\d+)' % tuple(map(re.escape, (thousands_sep, decimal_sep, decimal_sep)))) - self.thousand_check = re.compile(r'^[+-]?\d{1,3}(%s\d{3})*(%s\d*)?$' % tuple(map(re.escape, (thousands_sep, decimal_sep)))) - - @debug() - def filter(self, text): - if type(text) in (float, int, long): - text = str(text) - - if empty(text): - return self.default_or_raise(FormatError('Unable to parse %r' % text)) - - original_text = text = super(CleanDecimal, self).filter(text) - - if self.legacy: - if self.replace_dots: - if type(self.replace_dots) is tuple: - thousands_sep, decimal_sep = self.replace_dots - else: - thousands_sep, decimal_sep = '.', ',' - text = text.replace(thousands_sep, '').replace(decimal_sep, '.') - - text = re.sub(r'[^\d\-\.]', '', text) - else: - thousands_sep, decimal_sep = self.replace_dots - - matches = self.matching.findall(text) - if not matches: - return self.default_or_raise(NumberFormatError('There is no number to parse')) - elif len(matches) > 1: - return self.default_or_raise(NumberFormatError('There should be exactly one number to parse')) - - text = '%s%s' % (matches[0][0], matches[0][1].strip()) - - if thousands_sep and thousands_sep in text and not self.thousand_check.match(text): - return self.default_or_raise(NumberFormatError('Thousands separator is misplaced in %r' % text)) - - text = text.replace(thousands_sep, '').replace(decimal_sep, '.') - - try: - v = Decimal(text) - if self.sign: - v *= self.sign(original_text) - return v - except InvalidOperation as e: - return self.default_or_raise(NumberFormatError(e)) - - @classmethod - def US(cls, *args, **kwargs): - kwargs['legacy'] = False - kwargs['replace_dots'] = (',', '.') - return cls(*args, **kwargs) - - @classmethod - def French(cls, *args, **kwargs): - kwargs['legacy'] = False - kwargs['replace_dots'] = (' ', ',') - return cls(*args, **kwargs) - - @classmethod - def SI(cls, *args, **kwargs): - kwargs['legacy'] = False - kwargs['replace_dots'] = (' ', '.') - return cls(*args, **kwargs) - - -from weboob.browser.filters.standard import Slugify as _Slugify -class Slugify(_Slugify): - @debug() - def filter(self, label): - label = re.sub(r'[^A-Za-z0-9]', ' ', label.lower()).strip() - label = re.sub(r'\s+', '-', label) - return label - - -from weboob.browser.filters.standard import Type as _Type -class Type(_Type): +class Coalesce(MultiFilter): """ - Get a cleaned value of any type from an element text. - The type_func can be any callable (class, function, etc.). - By default an empty string will not be parsed but it can be changed - by specifying minlen=False. Otherwise, a minimal length can be specified. - - >>> Type(CleanText('./td[1]'), type=int) # doctest: +SKIP - - >>> Type(type=int).filter(42) - 42 - >>> Type(type=int).filter('42') - 42 - >>> Type(type=int, default='NaN').filter('') - 'NaN' - >>> Type(type=list, minlen=False, default=list('ab')).filter('') - [] - >>> Type(type=list, minlen=0, default=list('ab')).filter('') - ['a', 'b'] + Returns the first value that is not falsy, + or default if all values are falsy. """ - - def __init__(self, selector=None, type=None, minlen=0, default=_NO_DEFAULT): - super(Type, self).__init__(selector, default=default) - self.type_func = type - self.minlen = minlen - @debug() - def filter(self, txt): - if isinstance(txt, self.type_func): - return txt - if empty(txt): - return self.default_or_raise(FormatError('Unable to parse %r' % txt)) - if self.minlen is not False and len(txt) <= self.minlen: - return self.default_or_raise(FormatError('Unable to parse %r' % txt)) - try: - return self.type_func(txt) - except ValueError as e: - return self.default_or_raise(FormatError('Unable to parse %r: %s' % (txt, e))) - - -from weboob.browser.filters.standard import Field as _Field -class Field(_Field): - """ - Get the attribute of object. - - Example:: + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) - obj_foo = CleanText('//h1') - obj_bar = Field('foo') - will make "bar" field equal to "foo" field. +class MapIn(Filter): """ - - def __init__(self, name): - super(Field, self).__init__() - self.name = name - - def __call__(self, item): - return item.use_selector(getattr(item, 'obj_%s' % self.name), key=self._key) - - -# Based on nth from https://docs.python.org/2/library/itertools.html -def nth(iterable, n, default=None): - "Returns the nth item or a default value, n can be negative, or '*' for all" - if n == '*': - return iterable - if n < 0: - iterable = reversed(list(iterable)) - n = abs(n) - 1 - return next(islice(iterable, n, None), default) - - -def ordinal(n): - "To have some readable debug information: '*' => all, 0 => 1st, 1 => 2nd..." - if n == '*': - return 'all' - i = abs(n) - n = n - 1 if n < 0 else n + 1 - return str(n) + ('th' if i > 2 else ['st', 'nd', 'rd'][i]) - - -from weboob.browser.filters.standard import Regexp as _Regexp -class Regexp(_Regexp): - r""" - Apply a regex. - - >>> from lxml.html import etree - >>> doc = etree.fromstring('

Date: 13/08/1988

') - >>> Regexp(CleanText('//p'), r'Date: (\d+)/(\d+)/(\d+)', '\\3-\\2-\\1')(doc) == u'1988-08-13' - True - - >>> (Regexp(CleanText('//body'), r'(\d+)', nth=1))(doc) == u'08' - True - >>> (Regexp(CleanText('//body'), r'(\d+)', nth=-1))(doc) == u'1988' - True - >>> (Regexp(CleanText('//body'), r'(\d+)', template='[\\1]', nth='*'))(doc) == [u'[13]', u'[08]', u'[1988]'] - True - >>> (Regexp(CleanText('//body'), r'Date:.*'))(doc) == u'Date: 13/08/1988' - True - >>> (Regexp(CleanText('//body'), r'^(?!Date:).*', default=None))(doc) - >>> - """ - - def __init__(self, selector=None, pattern=None, template=None, nth=0, flags=0, default=_NO_DEFAULT): - super(Regexp, self).__init__(selector, default=default) - assert pattern is not None - self.pattern = pattern - self._regex = re.compile(pattern, flags) - self.template = template - self.nth = nth - - def expand(self, m): - if self.template is None: - try: - return next(g for g in m.groups() if g is not None) - except StopIteration: - return m.string - return self.template(m) if callable(self.template) else m.expand(self.template) - - @debug() - def filter(self, txt): - """ - :raises: :class:`RegexpError` if `pattern` was not found - """ - - if isinstance(txt, (tuple, list)): - txt = u' '.join([t.strip() for t in txt.itertext()]) - - m = self._regex.search(txt) if self.nth == 0 else \ - nth(self._regex.finditer(txt), self.nth) - if not m: - msg = 'Unable to find %s %s in %r' % (ordinal(self.nth), self.pattern, txt) - return self.default_or_raise(RegexpError(msg)) - - if isinstance(m, Iterator): - return list(map(self.expand, m)) - - return self.expand(m) - - -from weboob.browser.filters.standard import Map as _Map -class Map(_Map): - """Map selected value to another value using a dict. - - Example:: - - TYPES = { - 'Concert': CATEGORIES.CONCERT, - 'Cinéma': CATEGORIES.CINE, - } - - obj_type = Map(CleanText('./li'), TYPES) + Map the pattern of a selected value to another value using a dict. """ def __init__(self, selector, map_dict, default=_NO_DEFAULT): """ :param selector: key from `map_dict` to use """ - - super(Map, self).__init__(selector, default=default) + super(MapIn, self).__init__(selector, default=default) self.map_dict = map_dict @debug() def filter(self, txt): """ - :raises: :class:`ItemNotFound` if key does not exist in dict - """ - - try: - return self.map_dict[txt] - except KeyError: - return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) - - -from weboob.browser.filters.standard import DateTime as _DateTime -class DateTime(_DateTime): - """Parse date and time.""" - - def __init__(self, selector=None, default=_NO_DEFAULT, dayfirst=False, translations=None, - parse_func=parse_date, fuzzy=False): - """ - :param dayfirst: if True, the day is be the first element in the string to parse - :type dayfirst: bool - :param parse_func: the function to use for parsing the datetime - :param translations: string replacements from site locale to English - :type translations: list[tuple[str, str]] + :raises: :class:`ItemNotFound` if key pattern does not exist in dict """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] - super(DateTime, self).__init__(selector, default=default) - self.dayfirst = dayfirst - self.translations = translations - self.parse_func = parse_func - self.fuzzy = fuzzy - - @debug() - def filter(self, txt): - if empty(txt) or txt == '': - return self.default_or_raise(FormatError('Unable to parse %r' % txt)) - try: - if self.translations: - for search, repl in self.translations: - txt = search.sub(repl, txt) - return self.parse_func(txt, dayfirst=self.dayfirst, fuzzy=self.fuzzy) - except (ValueError, TypeError) as e: - return self.default_or_raise(FormatError('Unable to parse %r: %s' % (txt, e))) - - -from weboob.browser.filters.standard import Date as _Date -class Date(_Date): - """Parse date.""" - - def __init__(self, selector=None, default=_NO_DEFAULT, dayfirst=False, translations=None, - parse_func=parse_date, fuzzy=False): - super(Date, self).__init__(selector, default=default, dayfirst=dayfirst, translations=translations, - parse_func=parse_func, fuzzy=fuzzy) - - @debug() - def filter(self, txt): - datetime = super(Date, self).filter(txt) - if hasattr(datetime, 'date'): - return datetime.date() - else: - return datetime - - -from weboob.browser.filters.standard import DateGuesser as _DateGuesser -class DateGuesser(_DateGuesser): - def __init__(self, selector, date_guesser, **kwargs): - super(DateGuesser, self).__init__(selector) - self.date_guesser = date_guesser - self.kwargs = kwargs - - def __call__(self, item): - values = self.select(self.selector, item) - date_guesser = self.date_guesser - # In case Env() is used to kive date_guesser. - if isinstance(date_guesser, _Filter): - date_guesser = self.select(date_guesser, item) - - if isinstance(values, basestring): - values = re.split('[/-]', values) - if len(values) == 2: - day, month = map(int, values) - else: - raise FormatError('Unable to take (day, month) tuple from %r' % values) - return date_guesser.guess_date(day, month, **self.kwargs) - - -from weboob.browser.filters.standard import Time as _Time -class Time(_Time): - """Parse time.""" - - klass = datetime.time - _regexp = re.compile(r'(?P\d+)[:h]?(?P\d+)([:m](?P\d+))?') - kwargs = {'hour': 'hh', 'minute': 'mm', 'second': 'ss'} - - def __init__(self, selector=None, default=_NO_DEFAULT): - super(Time, self).__init__(selector, default=default) - - @debug() - def filter(self, txt): - m = self._regexp.search(txt) - if m: - kwargs = {} - for key, index in self.kwargs.items(): - kwargs[key] = int(m.groupdict()[index] or 0) - return self.klass(**kwargs) - - return self.default_or_raise(FormatError('Unable to find time in %r' % txt)) - - -from weboob.browser.filters.standard import Duration as _Duration -class Duration(_Duration): - """Parse a duration as timedelta.""" - - klass = datetime.timedelta - _regexp = re.compile(r'((?P\d+)[:;])?(?P\d+)[;:](?P\d+)') - kwargs = {'hours': 'hh', 'minutes': 'mm', 'seconds': 'ss'} - - -from weboob.browser.filters.standard import MultiFilter as _MultiFilter -class MultiFilter(_MultiFilter): - def __init__(self, *args, **kwargs): - default = kwargs.pop('default', _NO_DEFAULT) - super(MultiFilter, self).__init__(args, default) - - def __call__(self, item): - values = [self.select(selector, item) for selector in self.selector] - return self.filter(tuple(values)) - - def filter(self, values): - raise NotImplementedError() - - -from weboob.browser.filters.standard import CombineDate as _CombineDate -class CombineDate(_CombineDate): - """Combine separate Date and Time filters into a single datetime.""" - - def __init__(self, date, time): - """ - :type date: filter - :type time: filter - """ - super(CombineDate, self).__init__(date, time) - - @debug() - def filter(self, values): - return datetime.datetime.combine(values[0], values[1]) - - -from weboob.browser.filters.standard import Format as _Format -class Format(_Format): - """Combine multiple filters with string-format. - - Example:: - - obj_title = Format('%s (%s)', CleanText('//h1'), CleanText('//h2')) - - will concatenate the text from all ``

`` and all ``

`` (but put - the latter between parentheses). - """ - - def __init__(self, fmt, *args): - """ - :param fmt: string format suitable for "%"-formatting - :type fmt: str - :param args: other filters to insert in `fmt` string. - There should be as many args as there are "%" in `fmt`. - """ - super(Format, self).__init__(*args) - self.fmt = fmt - - @debug() - def filter(self, values): - return self.fmt % values - - -from weboob.browser.filters.standard import BrowserURL as _BrowserURL -class BrowserURL(_BrowserURL): - def __init__(self, url_name, **kwargs): - super(BrowserURL, self).__init__(*kwargs.values()) - self.url_name = url_name - self.keys = list(kwargs.keys()) - - def __call__(self, item): - values = super(BrowserURL, self).__call__(item) - url = getattr(item.page.browser, self.url_name) - assert isinstance(url, URL), "%s.%s must be an URL object" % (type(item.page.browser).__name__, self.url_name) - return url.build(**dict(zip(self.keys, values))) - - @debug() - def filter(self, values): - return values - - -from weboob.browser.filters.standard import Join as _Join -class Join(_Join): - def __init__(self, pattern, selector=None, textCleaner=CleanText, newline=False, addBefore='', addAfter=''): - super(Join, self).__init__(selector) - self.pattern = pattern - self.textCleaner = textCleaner - self.newline = newline - self.addBefore = addBefore - self.addAfter = addAfter - - @debug() - def filter(self, el): - items = [self.textCleaner.clean(e) for e in el] - items = [item for item in items if item] - - if self.newline: - items = ['%s\r\n' % item for item in items] - - result = self.pattern.join(items) - - if self.addBefore: - result = '%s%s' % (self.addBefore, result) - - if self.addAfter: - result = '%s%s' % (result, self.addAfter) - - return result - - -from weboob.browser.filters.standard import Eval as _Eval -class Eval(_Eval): - """ - Evaluate a function with given 'deferred' arguments. - - >>> F = Field; Eval(lambda a, b, c: a * b + c, F('foo'), F('bar'), F('baz')) # doctest: +SKIP - >>> Eval(lambda x, y: x * y + 1).filter([3, 7]) - 22 - - Example:: - - obj_ratio = Eval(lambda x: x / 100, Env('percentage')) - """ - - def __init__(self, func, *args): - """ - :param func: function to apply to all filters. The function should - accept as many args as there are filters passed to - Eval. - """ - super(Eval, self).__init__(*args) - self.func = func - - @debug() - def filter(self, values): - return self.func(*values) - - -from weboob.browser.filters.standard import QueryValue as _QueryValue -class QueryValue(_QueryValue): - """ - Extract the value of a parameter from an URL with a query string. - - >>> from lxml.html import etree - >>> from .html import Link - >>> f = QueryValue(Link('//a'), 'id') - >>> f(etree.fromstring('')) == u'1234' - True - """ - def __init__(self, selector, key, default=_NO_DEFAULT): - super(QueryValue, self).__init__(selector, default=default) - self.querykey = key - - @debug() - def filter(self, url): - qs = parse_qs(urlparse(url).query) - if not qs.get(self.querykey): - return self.default_or_raise(ItemNotFound('Key %s not found' % self.querykey)) - if len(qs[self.querykey]) > 1: - raise FilterError('More than one value for key %s' % self.querykey) - return qs[self.querykey][0] - - -class Coalesce(MultiFilter): - """ - Returns the first value that is not falsy, - or default if all values are falsy. - """ - @debug() - def filter(self, values): - for value in values: - if value: - return value - return self.default_or_raise(FilterError('All falsy and no default.')) - - -def test_CleanText(): - # This test works poorly under a doctest, or would be hard to read - assert CleanText().filter(u' coucou  \n\théhé') == u'coucou héhé' - assert CleanText().filter('coucou\xa0coucou') == CleanText().filter(u'coucou\xa0coucou') == u'coucou coucou' - - # Unicode normalization - assert CleanText().filter(u'Éçã') == u'Éçã' - assert CleanText(normalize='NFKC').filter(u'…') == u'...' - assert CleanText().filter(u'…') == u'…' - # Diacritical mark (dakuten) - assert CleanText().filter(u'\u3053\u3099') == u'\u3054' - assert CleanText(normalize='NFD').filter(u'\u3053\u3099') == u'\u3053\u3099' - assert CleanText(normalize='NFD').filter(u'\u3054') == u'\u3053\u3099' - assert CleanText(normalize=False).filter(u'\u3053\u3099') == u'\u3053\u3099' - - -def assert_raises(exc_class, func, *args, **kwargs): - try: - func(*args, **kwargs) - except exc_class: - pass - else: - assert False, 'did not raise %s' % exc_class - - -def test_CleanDecimal_strict(): - assert CleanDecimal.US().filter('123') == Decimal('123') - assert CleanDecimal.US().filter('foo + 123 bar') == Decimal('123') - assert CleanDecimal.US().filter('foo +123 bar') == Decimal('123') - assert CleanDecimal.US().filter('foo 123.45 bar') == Decimal('123.45') - assert CleanDecimal.US().filter('foo 12,345.67 bar') == Decimal('12345.67') - assert CleanDecimal.US().filter('foo 123,456,789 bar') == Decimal('123456789') - assert CleanDecimal.US().filter('foo - 123,456,789.1 bar') == Decimal('-123456789.1') - assert CleanDecimal.US().filter('foo -123,456,789.1 bar') == Decimal('-123456789.1') - assert CleanDecimal.US().filter('foo - .1 bar') == Decimal('-0.1') - assert CleanDecimal.US().filter('foo -.1 bar') == Decimal('-0.1') - assert_raises(NumberFormatError, CleanDecimal.US().filter, 'foo 12 345.67 bar') - assert_raises(NumberFormatError, CleanDecimal.US().filter, 'foo 123 bar 456') - assert_raises(NumberFormatError, CleanDecimal.US().filter, 'foo 123.456.789 bar') - assert_raises(NumberFormatError, CleanDecimal.US().filter, 'foo 12,3456 bar') - assert_raises(NumberFormatError, CleanDecimal.US().filter, 'foo 123-456 bar') - - assert CleanDecimal.French().filter('123') == Decimal('123') - assert CleanDecimal.French().filter('foo + 123 bar') == Decimal('123') - assert CleanDecimal.French().filter('foo +123 bar') == Decimal('123') - assert CleanDecimal.French().filter('foo 123,45 bar') == Decimal('123.45') - assert CleanDecimal.French().filter('foo 12 345,67 bar') == Decimal('12345.67') - assert CleanDecimal.French().filter('foo - 123 456 789 bar') == Decimal('-123456789') - assert CleanDecimal.French().filter('foo -123 456 789 bar') == Decimal('-123456789') - assert_raises(NumberFormatError, CleanDecimal.French().filter, 'foo 123.45 bar') - assert_raises(NumberFormatError, CleanDecimal.French().filter, 'foo 123 bar 456') - assert_raises(NumberFormatError, CleanDecimal.French().filter, 'foo 123,456,789') - assert_raises(NumberFormatError, CleanDecimal.French().filter, 'foo 12 3456 bar') - assert_raises(NumberFormatError, CleanDecimal.French().filter, 'foo 123-456 bar') - - assert CleanDecimal.SI().filter('123') == Decimal('123') - assert CleanDecimal.SI().filter('foo + 123 bar') == Decimal('123') - assert CleanDecimal.SI().filter('foo +123 bar') == Decimal('123') - assert CleanDecimal.SI().filter('foo 123.45 bar') == Decimal('123.45') - assert CleanDecimal.SI().filter('foo 12 345.67 bar') == Decimal('12345.67') - assert CleanDecimal.SI().filter('foo 123 456 789 bar') == Decimal('123456789') - assert CleanDecimal.SI().filter('foo - 123 456 789 bar') == Decimal('-123456789') - assert CleanDecimal.SI().filter('foo -123 456 789 bar') == Decimal('-123456789') - assert_raises(NumberFormatError, CleanDecimal.SI().filter, 'foo 123,45 bar') - assert_raises(NumberFormatError, CleanDecimal.SI().filter, 'foo 123 bar 456') - assert_raises(NumberFormatError, CleanDecimal.SI().filter, 'foo 123,456,789') - assert_raises(NumberFormatError, CleanDecimal.SI().filter, 'foo 12 3456 bar') - assert_raises(NumberFormatError, CleanDecimal.SI().filter, 'foo 123-456 bar') - + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cragr/api/pages.py b/modules/cragr/api/pages.py index 27cb8fd4ec..0ec8bc22f5 100644 --- a/modules/cragr/api/pages.py +++ b/modules/cragr/api/pages.py @@ -34,7 +34,7 @@ from weboob.capabilities.profile import Person, Company from weboob.capabilities.contact import Advisor from weboob.browser.elements import DictElement, ItemElement, method -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Currency as CleanCurrency, Format, Field, Map, Eval, Env, Regexp, Date, ) from weboob.browser.filters.html import Attr diff --git a/modules/cragr/api/transfer_pages.py b/modules/cragr/api/transfer_pages.py index 4447d38b28..aaf4e313b4 100644 --- a/modules/cragr/api/transfer_pages.py +++ b/modules/cragr/api/transfer_pages.py @@ -77,6 +77,7 @@ def condition(self): obj_category = 'Interne' obj_enabled_at = date.today() obj__is_recipient = Dict('recipientOfTransfert', default=False) + obj__owner_name = CleanText(Dict('accountHolderLongDesignation')) @method class iter_external_recipient(DictElement): @@ -90,7 +91,7 @@ def condition(self): klass = Recipient obj_id = obj_iban = Dict('ibanCode') - obj_label = Dict('recipientName') + obj_label = CleanText(Dict('recipientName')) obj_category = 'Externe' obj_enabled_at = date.today() @@ -123,8 +124,12 @@ def handle_response(self, transfer): t.account_iban = Dict('currentDebitIbanCode')(self.doc) t.account_label = Dict('typeCompte')(self.doc) + t.recipient_label = CleanText(Dict('currentCreditAccountName'))(self.doc) t.recipient_id = t.recipient_iban = Dict('currentCreditIbanCode')(self.doc) - t.recipient_label = Dict('currentCreditAccountName')(self.doc) + + # Internal transfer + if not Dict('isExternalTransfer')(self.doc): + t.recipient_id = Dict('currentCreditAccountNumber')(self.doc) return t diff --git a/modules/cragr/web/browser.py b/modules/cragr/web/browser.py index 5fe416e43f..b9c5019b5c 100644 --- a/modules/cragr/web/browser.py +++ b/modules/cragr/web/browser.py @@ -30,13 +30,13 @@ ) from weboob.capabilities.base import find_object, empty from weboob.capabilities.profile import ProfileMissing -from weboob.browser import LoginBrowser, URL, need_login, StatesMixin +from weboob.browser.browsers import LoginBrowser, URL, need_login, StatesMixin from weboob.browser.switch import SiteSwitch from weboob.browser.pages import FormNotFound from weboob.exceptions import BrowserIncorrectPassword, BrowserUnavailable from weboob.tools.date import ChaoticDateGuesser, LinearDateGuesser from weboob.exceptions import BrowserHTTPError, ActionNeeded -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.tools.value import Value from weboob.tools.compat import urlparse, urljoin, basestring from weboob.tools.capabilities.bank.iban import is_iban_valid diff --git a/modules/cragr/web/compat/weboob_browser_filters_standard.py b/modules/cragr/web/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cragr/web/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cragr/web/pages.py b/modules/cragr/web/pages.py index 8153266bd9..464047da38 100644 --- a/modules/cragr/web/pages.py +++ b/modules/cragr/web/pages.py @@ -38,7 +38,7 @@ from weboob.tools.date import parse_french_date, LinearDateGuesser from weboob.tools.compat import urlparse, urljoin, unicode from weboob.browser.elements import ListElement, TableElement, ItemElement, method -from weboob.browser.filters.standard import Date, CleanText, CleanDecimal, Currency as CleanCurrency, \ +from .compat.weboob_browser_filters_standard import Date, CleanText, CleanDecimal, Currency as CleanCurrency, \ Regexp, Format, Field from weboob.browser.filters.html import Link, TableCell, ColumnNotFound, Attr diff --git a/modules/creditdunord/browser.py b/modules/creditdunord/browser.py index 73e2f520fb..21f6764986 100644 --- a/modules/creditdunord/browser.py +++ b/modules/creditdunord/browser.py @@ -36,6 +36,7 @@ class CreditDuNordBrowser(LoginBrowser): login = URL('$', '/.*\?.*_pageLabel=page_erreur_connexion', + '/.*\?.*_pageLabel=reinitialisation_mot_de_passe', LoginPage) redirect = URL('/swm/redirectCDN.html', RedirectPage) entrypage = URL('/icd/zco/#zco', EntryPage) @@ -69,21 +70,20 @@ def do_login(self): if expired_error: raise BrowserPasswordExpired(expired_error) - if self.login.is_here(): + # Force redirection to entry page if the redirect page does not contain an url + if self.redirect.is_here(): + self.entrypage.go() + + if self.entrypage.is_here() or self.login.is_here(): error = self.page.get_error() if error: + if 'code confidentiel à la première connexion' in error: + raise BrowserPasswordExpired(error) raise BrowserIncorrectPassword(error) - else: - # in case we are still on login without error message - # we'll check what's happening. - assert False, "Still on login page." if not self.logged: raise BrowserIncorrectPassword() - if self.page.doc.xpath('//head[title="Authentification"]/script[contains(text(), "_pageLabel=reinitialisation_mot_de_passe")]'): - raise BrowserPasswordExpired() - def _iter_accounts(self): self.loans.go(account_type=self.account_type, loans_page_label=self.loans_page_label) for a in self.page.get_list(): diff --git a/modules/creditdunord/compat/weboob_browser_filters_standard.py b/modules/creditdunord/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/creditdunord/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/creditdunord/pages.py b/modules/creditdunord/pages.py index d677c13393..70b99df03a 100755 --- a/modules/creditdunord/pages.py +++ b/modules/creditdunord/pages.py @@ -29,7 +29,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage from weboob.browser.elements import method, ItemElement, TableElement -from weboob.browser.filters.standard import CleanText, Date, CleanDecimal, Regexp, Format, Field, Eval, Lower +from .compat.weboob_browser_filters_standard import CleanText, Date, CleanDecimal, Regexp, Format, Field, Eval, Lower from weboob.browser.filters.json import Dict from weboob.browser.filters.html import Attr, TableCell from weboob.exceptions import ActionNeeded, BrowserIncorrectPassword, BrowserUnavailable, BrowserPasswordExpired @@ -97,15 +97,26 @@ def get_string_code(self, string): return ','.join(res) +class HTMLErrorPage(HTMLPage): + def get_error(self): + # No Coalesce here as both can be empty + return CleanText('//b[has-class("x-attentionErreurLigneHaut")]')(self.doc) or \ + CleanText('//div[has-class("x-attentionErreur")]/b')(self.doc) + + + class RedirectPage(HTMLPage): - pass + def on_load(self): + link = Regexp(CleanText('//script'), 'href="(.*)"', default='')(self.doc) + if link: + self.browser.location(link) -class EntryPage(LoggedPage, HTMLPage): +class EntryPage(LoggedPage, HTMLErrorPage): pass -class LoginPage(HTMLPage): +class LoginPage(HTMLErrorPage): VIRTUALKEYBOARD = CDNVirtKeyboard def login(self, username, password): @@ -147,9 +158,6 @@ def classic_login(self, username, password): } self.browser.location('/saga/authentification', data=data) - def get_error(self): - return CleanText('//b[has-class("x-attentionErreurLigneHaut")]', default="")(self.doc) - class AccountTypePage(LoggedPage, JsonPage): def get_account_type(self): diff --git a/modules/creditdunordpee/compat/weboob_browser_filters_standard.py b/modules/creditdunordpee/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/creditdunordpee/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/creditdunordpee/compat/weboob_tools_captcha_virtkeyboard.py b/modules/creditdunordpee/compat/weboob_tools_captcha_virtkeyboard.py deleted file mode 100644 index 3f29ddc260..0000000000 --- a/modules/creditdunordpee/compat/weboob_tools_captcha_virtkeyboard.py +++ /dev/null @@ -1,196 +0,0 @@ - -import weboob.tools.captcha.virtkeyboard as OLD - -# can't import *, __all__ is incomplete... -for attr in dir(OLD): - globals()[attr] = getattr(OLD, attr) - - -try: - __all__ = OLD.__all__ -except AttributeError: - pass - - -class SimpleVirtualKeyboard(object): - """Handle a virtual keyboard where "keys" are distributed on a simple grid. - - Parameters: - :param cols: Column count of the grid - :type cols: int - :param rows: Row count of the grid - :type rows: int - :param image: File-like object to be used as data source - :type image: file - :param convert: Mode to which convert color of pixels, see - :meth:`Image.Image.convert` for more information - :param matching_symbols: symbol that match all case of image grid from left to right and top - to down, European reading way. - :type matching_symbols: iterable - :param matching_symbols_coords: dict mapping matching website symbols to their image coords - (x0, y0, x1, y1) on grid image from left to right and top to - down, European reading way. It's not symbols in the image. - :type matching_symbols_coords: dict[str:4-tuple(int)] - :param browser: Browser of weboob session. - Allow to dump tiles files in same directory than session folder - :type browser: obj(Browser) - - Attributes: - :attribute codesep: Output separator between matching symbols - :type codesep: str - :param margin: Useless image pixel to cut. - See :func:`cut_margin`. - :type margin: 4-tuple(int), same as HTML margin: (top, right, bottom, left). - or 2-tuple(int), (top = bottom, right = left), - or int, top = right = bottom = left - :attribute tile_margin: Useless tile pixel to cut. - See :func:`cut_margin`. - :attribute symbols: Association table between image symbols and md5s - :type symbols: dict[str:str] or dict[str:n-tuple(str)] - :attribute convert: Mode to which convert color of pixels, see - :meth:`Image.Image.convert` for more information - :attribute alter: Allow custom main image alteration. Then overwrite :func:`alter_image`. - :type alter: boolean - """ - - codesep = '' - margin = None - tile_margin = None - symbols = None - convert = None - - def __init__(self, file, cols, rows, matching_symbols=None, matching_symbols_coords=None, browser=None): - self.cols = cols - self.rows = rows - - # Needed even if init is overwrite - self.path = self.build_path(browser) - - # Get self.image - self.load_image(file, self.margin, self.convert) - - # Get self.tiles - self.get_tiles( matching_symbols=matching_symbols, - matching_symbols_coords=matching_symbols_coords) - - # Tiles processing - self.cut_tiles(self.tile_margin) - self.hash_md5_tiles() - - def build_path(self, browser=None): - if browser and browser.responses_dirname: - return browser.responses_dirname - else: - return tempfile.mkdtemp(prefix='weboob_session_') - - def load_image(self, file, margin=None, convert=None): - self.image = Image.open(file) - # Resize image if margin is given - if margin: - self.image = self.cut_margin(self.image, margin) - if convert: - self.image = self.image.convert(convert) - # Give possibility to alter image before get tiles, overwrite :func:`alter_image`. - self.alter_image() - self.width, self.height = self.image.size - - def alter_image(self): - pass - - def cut_margin(self, image, margin): - width, height = image.size - - # Verify the magin value format - if type(margin) is int: - margin = (margin, margin, margin, margin) - elif len(margin) == 2: - margin = (margin[0], margin[1], margin[0], margin[1]) - elif len(margin) == 4: - margin = margin - else: - assert (len(margin) == 3) & (len(margin) > 4), \ - "Margin format is wrong." - - assert ((margin[0] + margin[2]) < height) & ((margin[1] + margin[3]) < width), \ - "Margin is too high, there is not enough pixel to cut." - - image = image.crop((0 + margin[3], - 0 + margin[0], - width - margin[1], - height - margin[2] - )) - return image - - def get_tiles(self, matching_symbols=None, matching_symbols_coords=None): - self.tiles = [] - - # Tiles coords are given - if matching_symbols_coords: - for matching_symbol in matching_symbols_coords: - self.tiles.append(Tile( matching_symbol=matching_symbol, - coords=matching_symbols_coords[matching_symbol] - )) - return - - assert (not self.width%self.cols) & (not self.height%self.rows), \ - "Image width and height are not multiple of cols and rows. Please resize image with attribute `margin`." - - # Tiles coords aren't given, calculate them - self.tileW = self.width // self.cols - self.tileH = self.height // self.rows - - # Matching symbols aren't given, default value is range(columns*rows) - if not matching_symbols: - matching_symbols = ['%s' % i for i in range(self.cols*self.rows)] - - assert len(matching_symbols) == (self.cols*self.rows), \ - "Number of website matching symbols is not equal to the number of cases on the image." - - # Calculate tiles coords for each matching symbol from 1-dimension to 2-dimensions - for index, matching_symbol in enumerate(matching_symbols): - coords = self.get_tile_coords_in_grid(index) - self.tiles.append(Tile(matching_symbol=matching_symbol, coords=coords)) - - def get_tile_coords_in_grid(self, case_index): - # Get the top left pixel coords of the tile - x0 = (case_index % self.cols) * self.tileW - y0 = (case_index // self.cols) * self.tileH - - # Get the bottom right coords of the tile - x1 = x0 + self.tileW - y1 = y0 + self.tileH - - coords = (x0, y0, x1, y1) - return(coords) - - def cut_tiles(self, tile_margin=None): - for tile in self.tiles: - tile.image = self.image.crop(tile.coords) - - # Resize tile if margin is given - if tile_margin: - for tile in self.tiles: - tile.image = self.cut_margin(tile.image, tile_margin) - - def hash_md5_tiles(self): - for tile in self.tiles: - tile.md5 = hashlib.md5(tile.image.tobytes()).hexdigest() - - def dump_tiles(self, path): - for tile in self.tiles: - tile.image.save('{}/{}.png'.format(path, tile.md5)) - - def get_string_code(self, password): - word = [] - - for digit in password: - for tile in self.tiles: - if tile.md5 in self.symbols[digit]: - word.append(tile.matching_symbol) - break - else: - # Dump file only if the symbol is not found - self.dump_tiles(self.path) - raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s" - % (digit, self.path)) - return self.codesep.join(word) diff --git a/modules/creditdunordpee/pages.py b/modules/creditdunordpee/pages.py index 0382f3f4d7..e54ea1b56a 100644 --- a/modules/creditdunordpee/pages.py +++ b/modules/creditdunordpee/pages.py @@ -25,7 +25,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from .compat.weboob_tools_captcha_virtkeyboard import MappedVirtKeyboard from weboob.browser.elements import ItemElement, TableElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Format, Regexp, Date, Env, Currency, Eval +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Format, Regexp, Date, Env, Currency, Eval from weboob.browser.filters.html import CleanHTML, TableCell from weboob.capabilities.bank import Account, Transaction, Investment from weboob.capabilities.base import NotAvailable diff --git a/modules/creditmutuel/browser.py b/modules/creditmutuel/browser.py index 80710eec78..be2e24cf7c 100644 --- a/modules/creditmutuel/browser.py +++ b/modules/creditmutuel/browser.py @@ -421,6 +421,7 @@ def get_history(self, account): history = self.page.get_history(date=self.tr_date) for tr in history: + # For regrouped transaction, we have to go through each one to get details if tr._regroup: self.location(tr._regroup) for tr2 in self.page.get_tr_merged(): diff --git a/modules/creditmutuel/compat/__init__.py b/modules/creditmutuel/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/creditmutuel/compat/weboob_browser_filters_standard.py b/modules/creditmutuel/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/creditmutuel/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/creditmutuel/pages.py b/modules/creditmutuel/pages.py index f311e236e4..bd08936f29 100644 --- a/modules/creditmutuel/pages.py +++ b/modules/creditmutuel/pages.py @@ -30,7 +30,7 @@ from weboob.browser.pages import HTMLPage, FormNotFound, LoggedPage, pagination, XMLPage from weboob.browser.elements import ListElement, ItemElement, SkipItem, method, TableElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( Filter, Env, CleanText, CleanDecimal, Field, Regexp, Async, AsyncLoad, Date, Format, Type, Currency, ) from weboob.browser.filters.html import Link, Attr, TableCell, ColumnNotFound @@ -725,7 +725,7 @@ class item(Transaction.TransactionElement): obj_original_amount = CleanDecimal(TableCell('original_amount'), default=NotAvailable, replace_dots=True) obj_original_currency = FrenchTransaction.Currency(TableCell('original_amount')) obj_type = Transaction.TYPE_DEFERRED_CARD - obj_rdate = Transaction.Date(TableCell('date')) + obj_rdate = obj_bdate = Transaction.Date(TableCell('date')) obj_date = obj_vdate = Env('date') obj__is_coming = Env('_is_coming') @@ -905,7 +905,7 @@ def condition(self): return len(self.el.xpath('./td')) >= 4 and not CleanText(TableCell('commerce'))(self).startswith('RETRAIT CB') obj_raw = Transaction.Raw(Format("%s %s", CleanText(TableCell('commerce')), CleanText(TableCell('ville')))) - obj_rdate = Field('vdate') + obj_rdate = obj_bdate = Field('vdate') obj_date = Env('date') def obj_type(self): @@ -933,6 +933,8 @@ def obj__is_coming(self): return True return False + # Some payment made on the same organization are regrouped, + # we have to get the detail for each one later def obj__regroup(self): if "Regroupement" in CleanText('./td')(self): return Link('./td/span/a')(self) @@ -959,6 +961,10 @@ def obj_type(self): return Transaction.TYPE_DEFERRED_CARD return Transaction.TYPE_CARD_SUMMARY + def obj_bdate(self): + if Field('type')(self) == Transaction.TYPE_DEFERRED_CARD: + return Transaction.Date(TableCell('date'))(self) + def has_more_operations(self): xp = CleanText(self.doc.xpath('//div[@class="ei_blocpaginb"]/a'))(self) if xp == 'Suite des opérations': @@ -985,7 +991,7 @@ def condition(self): return not CleanText(TableCell('commerce'))(self).startswith('RETRAIT CB') obj_raw = Transaction.Raw(Format("%s %s", CleanText(TableCell('commerce')), CleanText(TableCell('ville')))) - obj_rdate = Field('vdate') + obj_rdate = obj_bdate = Field('vdate') obj_date = Env('date') def obj_type(self): @@ -1162,9 +1168,11 @@ def obj_code(self): class PorPage(LoggedPage, HTMLPage): - TYPES = {"PLAN D'EPARGNE EN ACTIONS": Account.TYPE_PEA, - 'P.E.A': Account.TYPE_PEA - } + TYPES = { + "PLAN D'EPARGNE EN ACTIONS": Account.TYPE_PEA, + 'P.E.A': Account.TYPE_PEA, + 'PEA': Account.TYPE_PEA, + } def get_type(self, label): for pattern, actype in self.TYPES.items(): @@ -1539,10 +1547,7 @@ def parse(self, el): self.env['origin_account']._external_recipients.add(Field('id')(self)) def get_transfer_form(self): - # internal and external transfer form are differents - if self.IS_PRO_PAGE: - return self.get_form(id='P2:F', submit='//input[@type="submit" and contains(@value, "Valider")]') - return self.get_form(id='P1:F', submit='//input[@type="submit" and contains(@value, "Valider")]') + return self.get_form(xpath='//form[@id="P1:F"] | //form[@id="P2:F"]', submit='//input[@type="submit" and contains(@value, "Valider")]') class VerifCodePage(LoggedPage, HTMLPage): HASHES = { diff --git a/modules/cuisineaz/compat/__init__.py b/modules/cuisineaz/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/cuisineaz/compat/weboob_browser_filters_standard.py b/modules/cuisineaz/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/cuisineaz/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/cuisineaz/pages.py b/modules/cuisineaz/pages.py index 73099f1757..fc06f6157e 100644 --- a/modules/cuisineaz/pages.py +++ b/modules/cuisineaz/pages.py @@ -23,7 +23,7 @@ from weboob.capabilities.image import BaseImage, Thumbnail from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ItemElement, method, ListElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Regexp, Env, Time, Join, Format, Eval, ) from weboob.browser.filters.html import XPath diff --git a/modules/dailymotion/compat/__init__.py b/modules/dailymotion/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/dailymotion/compat/weboob_browser_filters_standard.py b/modules/dailymotion/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/dailymotion/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/dailymotion/pages.py b/modules/dailymotion/pages.py index 01d72772c5..d131dfc4ea 100644 --- a/modules/dailymotion/pages.py +++ b/modules/dailymotion/pages.py @@ -19,7 +19,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage, pagination -from weboob.browser.filters.standard import CleanText, Regexp, Env, Duration, DateTime +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env, Duration, DateTime from weboob.browser.filters.html import Link from weboob.capabilities.base import NotAvailable diff --git a/modules/delubac/compat/weboob_browser_filters_standard.py b/modules/delubac/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/delubac/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/delubac/pages.py b/modules/delubac/pages.py index df85bd1661..ea7702742e 100644 --- a/modules/delubac/pages.py +++ b/modules/delubac/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.exceptions import ParseError, ActionNeeded from .compat.weboob_tools_captcha_virtkeyboard import GridVirtKeyboard -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class DelubacVirtKeyboard(GridVirtKeyboard): diff --git a/modules/dlfp/pages/compat/__init__.py b/modules/dlfp/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/dlfp/pages/compat/weboob_browser_filters_standard.py b/modules/dlfp/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/dlfp/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/dlfp/pages/wiki.py b/modules/dlfp/pages/wiki.py index 4709640589..a4bd2a9431 100644 --- a/modules/dlfp/pages/wiki.py +++ b/modules/dlfp/pages/wiki.py @@ -19,7 +19,7 @@ import lxml.html -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from .index import DLFPPage diff --git a/modules/dresdenwetter/compat/__init__.py b/modules/dresdenwetter/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/dresdenwetter/compat/weboob_browser_filters_standard.py b/modules/dresdenwetter/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/dresdenwetter/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/dresdenwetter/pages.py b/modules/dresdenwetter/pages.py index af113d2aa3..017bfdc8c9 100644 --- a/modules/dresdenwetter/pages.py +++ b/modules/dresdenwetter/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Field, Filter, debug +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Field, Filter, debug from weboob.capabilities.gauge import GaugeMeasure, GaugeSensor from weboob.capabilities.base import NotAvailable diff --git a/modules/edf/module.py b/modules/edf/module.py index d13f26613a..1cb24c4edc 100644 --- a/modules/edf/module.py +++ b/modules/edf/module.py @@ -42,7 +42,7 @@ class EdfModule(Module, CapDocument, CapProfile): ValueBackendPassword('password', label='Mot de passe'), Value('website', label='Type de compte', default='par', choices={'par': 'Particulier', 'pro': 'Entreprise'}), - Value('captcha_response', label='Reponse Captcha', required=False, default='')) + Value('otp', label='Entrez le code reçu par SMS', required=False)) accepted_document_types = (DocumentTypes.BILL,) diff --git a/modules/edf/par/browser.py b/modules/edf/par/browser.py index 557ecb1512..8d3cb0580a 100644 --- a/modules/edf/par/browser.py +++ b/modules/edf/par/browser.py @@ -20,13 +20,13 @@ from time import time -from weboob.browser import LoginBrowser, URL, need_login -from weboob.browser.exceptions import ClientError -from weboob.exceptions import BrowserIncorrectPassword, NocaptchaQuestion +from weboob.browser import LoginBrowser, URL, need_login, StatesMixin +from weboob.exceptions import BrowserIncorrectPassword, BrowserQuestion from weboob.tools.decorators import retry from weboob.tools.json import json +from weboob.tools.value import Value from .pages import ( - HomePage, AuthenticatePage, AuthorizePage, CheckAuthenticatePage, ProfilPage, + HomePage, AuthenticatePage, AuthorizePage, WrongPasswordPage, CheckAuthenticatePage, ProfilPage, DocumentsPage, WelcomePage, UnLoggedPage, ProfilePage, BillDownload, ) @@ -35,13 +35,15 @@ class BrokenPageError(Exception): pass -class EdfBrowser(LoginBrowser): +class EdfBrowser(LoginBrowser, StatesMixin): BASEURL = 'https://particulier.edf.fr' home = URL('/fr/accueil/contrat-et-conso/mon-compte-edf.html', HomePage) authenticate = URL(r'https://espace-client.edf.fr/sso/json/authenticate', AuthenticatePage) authorize = URL(r'https://espace-client.edf.fr/sso/oauth2/INTERNET/authorize', AuthorizePage) + wrong_password = URL(r'https://espace-client.edf.fr/connexion/mon-espace-client/templates/openam/authn/PasswordAuth2.html', WrongPasswordPage) check_authenticate = URL('/services/rest/openid/checkAuthenticate', CheckAuthenticatePage) + user_status = URL('/services/rest/checkuserstatus/getUserStatus') not_connected = URL('/fr/accueil/connexion/mon-espace-client.html', UnLoggedPage) connected = URL('/fr/accueil/espace-client/tableau-de-bord.html', WelcomePage) profil = URL('/services/rest/authenticate/getListContracts', ProfilPage) @@ -54,52 +56,96 @@ class EdfBrowser(LoginBrowser): r'&di=(?P.*)&bn=(?P.*)&an=(?P.*)', BillDownload) profile = URL('/services/rest/context/getCustomerContext', ProfilePage) + __states__ = ['id_token1'] + def __init__(self, config, *args, **kwargs): self.config = config - self.authId = None + self.otp_data = None + self.otp_url = None + self.id_token1 = None kwargs['username'] = self.config['login'].get() kwargs['password'] = self.config['password'].get() super(EdfBrowser, self).__init__(*args, **kwargs) + def locate_browser(self, state): + pass + def do_login(self): + # ********** admire how login works on edf par website ********** + # login part on edf particulier website is very tricky + # FIRST time we connect we have an otp, BUT not password, we can't know if it is wrong at this moment + # SECOND time we use password, and not otp auth_params = {'realm': '/INTERNET'} - if self.config['captcha_response'].get() and self.authId: + + if self.config['otp'].get(): + self.otp_data['callbacks'][0]['input'][0]['value'] = self.config['otp'].get() + self.authenticate.go(json=self.otp_data, params=auth_params) + self.id_token1 = self.page.get_data()['callbacks'][1]['output'][0]['value'] + # id_token1 is VERY important, we keep it indefinitely, without it edf will ask again otp + else: + self.location('/bin/edf_rc/servlets/sasServlet', params={'processus': 'TDB'}) + if self.connected.is_here(): + # we are already logged + # sometimes even if password is wrong, you can be logged if you retry + self.logger.info('already logged') + return + + self.otp_url = self.url self.authenticate.go(method='POST', params=auth_params) data = self.page.get_data() - data['authId'] = self.authId data['callbacks'][0]['input'][0]['value'] = self.username - data['callbacks'][1]['input'][0]['value'] = self.password - data['callbacks'][2]['input'][0]['value'] = self.config['captcha_response'].get() - data['callbacks'][3]['input'][0]['value'] = '0' - - try: - self.authenticate.go(json=data, params=auth_params) - except ClientError as error: - resp = error.response - if resp.status_code == 401: - raise BrowserIncorrectPassword(resp.json()['message']) - raise - - self.session.cookies['ivoiream'] = self.page.get_data()['tokenId'] - - # go to this url will auto submit a form which will finalize login - self.connected.go() - - """ - call check_authenticate url before get subscription in profil, or we'll get an error 'invalid session' - we do nothing with this response (which contains false btw) - but edf website expect we call it before or will reject us - """ - self.check_authenticate.go() - else: - self.authenticate.go(method='POST', params=auth_params) - if self.page.has_captcha_request(): - data = self.page.get_data() - website_key = data['callbacks'][4]['output'][0]['value'] - website_url = "https://espace-client.edf.fr/sso/XUI/#login/&realm=%2FINTERNET" - self.authId = data['authId'] - raise NocaptchaQuestion(website_key=website_key, website_url=website_url) + self.authenticate.go(json=data, params=auth_params) + data = self.page.get_data() # yes, we have to get response and send it again, beautiful isn't it ? + if data['stage'] == 'UsernameAuth2': + # username is wrong + raise BrowserIncorrectPassword(data['callbacks'][1]['output'][0]['value']) + + if self.id_token1: + data['callbacks'][0]['input'][0]['value'] = self.id_token1 + else: + # the FIRST time we connect, we don't have id_token1, we have no choice, we'll receive an otp + data['callbacks'][0]['input'][0]['value'] = ' ' + + self.authenticate.go(json=data, params=auth_params) + data = self.page.get_data() + + assert data['stage'] in ('HOTPcust3', 'PasswordAuth2'), 'stage is %s' % data['stage'] + + if data['stage'] == 'HOTPcust3': # OTP part + if self.id_token1: + # this shouldn't happen except if id_token1 expire one day, who knows... + self.logger.warning('id_token1 is not null but edf ask again for otp') + + # a legend say this url is the answer to life the universe and everything, because it is use EVERYWHERE in login + self.authenticate.go(json=self.page.get_data(), params=auth_params) + self.otp_data = self.page.get_data() + label = self.otp_data['callbacks'][0]['output'][0]['value'] + raise BrowserQuestion(Value('otp', label=label)) + + if data['stage'] == 'PasswordAuth2': # password part + data['callbacks'][0]['input'][0]['value'] = self.password + self.authenticate.go(json=self.page.get_data(), params=auth_params) + + # should be SetPasAuth2 if password is ok + if self.page.get_data()['stage'] == 'PasswordAuth2': + attempt_number = self.page.get_data()['callbacks'][1]['output'][0]['value'] + # attempt_number is the number of wrong password + msg = self.wrong_password.go().get_wrongpass_message(attempt_number) + raise BrowserIncorrectPassword(msg) + + data = self.page.get_data() + # yes, send previous data again, i know i know + self.authenticate.go(json=data, params=auth_params) + self.session.cookies['ivoiream'] = self.page.get_token() + self.user_status.go() + + """ + call check_authenticate url before get subscription in profil, or we'll get an error 'invalid session' + we do nothing with this response (which contains false btw) + but edf website expect we call it before or will reject us + """ + self.check_authenticate.go() def get_csrf_token(self): return self.csrf_token.go(timestamp=int(time())).get_token() diff --git a/modules/edf/par/compat/__init__.py b/modules/edf/par/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/edf/par/compat/weboob_browser_filters_standard.py b/modules/edf/par/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/edf/par/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/edf/par/pages.py b/modules/edf/par/pages.py index 7cbe5fd7bc..768fef1681 100644 --- a/modules/edf/par/pages.py +++ b/modules/edf/par/pages.py @@ -24,7 +24,7 @@ from weboob.browser.filters.html import Attr from weboob.browser.pages import LoggedPage, JsonPage, HTMLPage, RawPage -from weboob.browser.filters.standard import Env, Format, Date, Eval +from .compat.weboob_browser_filters_standard import Env, Format, Date, Eval, CleanText, Regexp from weboob.browser.elements import ItemElement, DictElement, method from weboob.browser.filters.json import Dict from weboob.capabilities.bill import DocumentTypes, Bill, Subscription @@ -43,6 +43,9 @@ def has_captcha_request(self): def get_data(self): return self.doc + def get_token(self): + return self.doc['tokenId'] + class AuthorizePage(HTMLPage): def on_load(self): @@ -50,6 +53,20 @@ def on_load(self): self.get_form().submit() +class WrongPasswordPage(HTMLPage): + def get_wrongpass_message(self, attempt_number): + # edf website block access after 5 wrong password, and user will have to change his password + # this is very important because it can tell to user how much attempt it remains + script = CleanText('//script[contains(text(), "Mot de passe incorrect")]') + + if attempt_number > 0: + return Format('%s %s %s', + Regexp(script, r">(Mot de passe incorrect.*?)<"), + CleanText('//div[@class="arrow_box--content"]', children=False), int(attempt_number))(self.doc) + return Regexp(script, r">(Vous avez atteint.*?)<")(self.doc) + + + class WelcomePage(LoggedPage, HTMLPage): pass @@ -62,7 +79,11 @@ class UnLoggedPage(HTMLPage): pass -class ProfilPage(LoggedPage, JsonPage): +class ProfilPage(JsonPage): + @property + def logged(self): + return self.doc['errorCode'] == 0 + @method class iter_subscriptions(DictElement): item_xpath = 'customerAccordContracts' diff --git a/modules/edf/pro/compat/__init__.py b/modules/edf/pro/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/edf/pro/compat/weboob_browser_filters_standard.py b/modules/edf/pro/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/edf/pro/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/edf/pro/pages.py b/modules/edf/pro/pages.py index 1476b20206..b85c23ea4f 100644 --- a/modules/edf/pro/pages.py +++ b/modules/edf/pro/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import JsonPage, HTMLPage, RawPage, LoggedPage from weboob.browser.elements import DictElement, ItemElement, method -from weboob.browser.filters.standard import CleanDecimal, CleanText +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText from weboob.browser.filters.json import Dict from weboob.capabilities.bill import DocumentTypes, Subscription, Bill from weboob.exceptions import ActionNeeded diff --git a/modules/ekwateur/compat/__init__.py b/modules/ekwateur/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ekwateur/compat/weboob_browser_filters_standard.py b/modules/ekwateur/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ekwateur/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ekwateur/pages.py b/modules/ekwateur/pages.py index 0bfcee0f95..2832fdcb4c 100644 --- a/modules/ekwateur/pages.py +++ b/modules/ekwateur/pages.py @@ -24,7 +24,7 @@ ItemElement, ListElement, TableElement, method ) from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( Date, CleanDecimal, CleanText, Currency, Env, Format, Regexp, Slugify, TableCell ) diff --git a/modules/ensap/compat/__init__.py b/modules/ensap/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ensap/compat/weboob_browser_filters_standard.py b/modules/ensap/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ensap/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ensap/pages.py b/modules/ensap/pages.py index 9518296cab..fcc08e451f 100644 --- a/modules/ensap/pages.py +++ b/modules/ensap/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, DictElement, method from weboob.browser.filters.json import Dict from weboob.capabilities.bill import Subscription, Document -from weboob.browser.filters.standard import Date, CleanText, Format, Regexp +from .compat.weboob_browser_filters_standard import Date, CleanText, Format, Regexp class LoginPage(HTMLPage): diff --git a/modules/entreparticuliers/compat/__init__.py b/modules/entreparticuliers/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/entreparticuliers/compat/weboob_browser_filters_standard.py b/modules/entreparticuliers/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/entreparticuliers/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/entreparticuliers/pages.py b/modules/entreparticuliers/pages.py index a0748bfca9..52b668c814 100644 --- a/modules/entreparticuliers/pages.py +++ b/modules/entreparticuliers/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import JsonPage, XMLPage from weboob.browser.elements import ItemElement, DictElement, method from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanText, CleanDecimal, Env, Format, Filter, DateTime +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Env, Format, Filter, DateTime from weboob.capabilities.housing import (Housing, HousingPhoto, City, UTILITIES, ENERGY_CLASS, ADVERT_TYPES) from weboob.tools.capabilities.housing.housing import PricePerMeterFilter from weboob.capabilities.base import NotAvailable, Currency, empty diff --git a/modules/explorimmo/compat/__init__.py b/modules/explorimmo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/explorimmo/compat/weboob_browser_filters_standard.py b/modules/explorimmo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/explorimmo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/explorimmo/pages.py b/modules/explorimmo/pages.py index 35631b889b..dcbd37d571 100644 --- a/modules/explorimmo/pages.py +++ b/modules/explorimmo/pages.py @@ -26,7 +26,7 @@ from weboob.browser.filters.json import Dict from weboob.browser.elements import ItemElement, ListElement, DictElement, method from weboob.browser.pages import JsonPage, HTMLPage, pagination -from weboob.browser.filters.standard import (CleanText, CleanDecimal, Currency, +from .compat.weboob_browser_filters_standard import (CleanText, CleanDecimal, Currency, Regexp, Env, BrowserURL, Filter, Format) from weboob.browser.filters.html import Attr, CleanHTML, XPath diff --git a/modules/feedly/compat/__init__.py b/modules/feedly/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/feedly/compat/weboob_browser_filters_standard.py b/modules/feedly/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/feedly/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/feedly/pages.py b/modules/feedly/pages.py index 41a4abfc08..fb79d8724f 100644 --- a/modules/feedly/pages.py +++ b/modules/feedly/pages.py @@ -23,7 +23,7 @@ from weboob.capabilities.collection import Collection from weboob.browser.pages import JsonPage, LoggedPage from weboob.browser.elements import ItemElement, DictElement, method -from weboob.browser.filters.standard import CleanText, Format +from .compat.weboob_browser_filters_standard import CleanText, Format from weboob.browser.filters.json import Dict from weboob.browser.filters.html import CleanHTML diff --git a/modules/foncia/browser.py b/modules/foncia/browser.py index ea1e276438..ce1255812a 100644 --- a/modules/foncia/browser.py +++ b/modules/foncia/browser.py @@ -30,7 +30,7 @@ class FonciaBrowser(PagesBrowser): BASEURL = 'https://fr.foncia.com' cities = URL(r'/recherche/autocomplete\?term=(?P.+)', CitiesPage) - housing = URL(r'/(?P[^/]+)/.*/\d+.htm', HousingPage) + housing = URL(r'/(?P[^/]+)/.*\d+.htm', HousingPage) search_results = URL(r'/(?P[^/]+)/.*', SearchResultsPage) search = URL(r'/(?P.+)', SearchPage) diff --git a/modules/foncia/compat/__init__.py b/modules/foncia/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/foncia/compat/weboob_browser_filters_standard.py b/modules/foncia/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/foncia/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/foncia/constants.py b/modules/foncia/constants.py index 5b74c23b27..404f2af848 100644 --- a/modules/foncia/constants.py +++ b/modules/foncia/constants.py @@ -11,7 +11,7 @@ HOUSE_TYPES.HOUSE: ['maison'], HOUSE_TYPES.PARKING: ['parking'], HOUSE_TYPES.LAND: ['terrain'], - HOUSE_TYPES.OTHER: ['chambre', + HOUSE_TYPES.OTHER: ['chambre', 'programme-neuf', 'local-commercial', 'immeuble'] } @@ -19,6 +19,6 @@ POSTS_TYPES.RENT: ['appartement', 'maison', 'parking', 'chambre', 'local-commercial'], POSTS_TYPES.SALE: ['appartement', 'maison', 'parking', 'local-commercial', - 'terrain', 'immeuble'], + 'terrain', 'immeuble', 'programme-neuf'], POSTS_TYPES.FURNISHED_RENT: ['appartement-meuble'] } diff --git a/modules/foncia/pages.py b/modules/foncia/pages.py index 98ab18fe96..1e997bf0ce 100644 --- a/modules/foncia/pages.py +++ b/modules/foncia/pages.py @@ -22,7 +22,7 @@ import datetime from weboob.browser.pages import JsonPage, HTMLPage, pagination -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanDecimal, CleanText, Currency, Date, Env, Format, Regexp, RegexpError ) from weboob.browser.filters.html import AbsoluteLink, Attr, Link, XPathNotFound @@ -91,15 +91,18 @@ def obj_house_type(self): CleanText( '//div[has-class("MiniData")]//p[has-class("MiniData-item")][1]' ), - r'(\d*\.*\d*) .*' - ) + r'(\d*\.*\d*) .*', + default=NotAvailable + ), + default=NotAvailable ) obj_cost = CleanDecimal( - '//p[has-class("OfferTop-price")]' + '//span[has-class("OfferTop-price")]', + default=NotAvailable ) obj_price_per_meter = PricePerMeterFilter() obj_currency = Currency( - '//p[has-class("OfferTop-price")]' + '//span[has-class("OfferTop-price")]' ) obj_location = Format( '%s - %s', @@ -302,8 +305,10 @@ def obj_house_type(self): CleanText( './/div[has-class("MiniData")]//p[@data-behat="surfaceDesBiens"]' ), - r'(\d*\.*\d*) .*' - ) + r'(\d*\.*\d*) .*', + default=NotAvailable + ), + default=NotAvailable ) obj_cost = CleanDecimal( './/strong[has-class("TeaserOffer-price-num")]' diff --git a/modules/fortuneo/pages/accounts_list.py b/modules/fortuneo/pages/accounts_list.py index 9ae95a975a..86f2d72906 100644 --- a/modules/fortuneo/pages/accounts_list.py +++ b/modules/fortuneo/pages/accounts_list.py @@ -29,7 +29,7 @@ from weboob.browser.elements import method, ItemElement from weboob.browser.filters.html import Link, Attr -from weboob.browser.filters.standard import CleanText, CleanDecimal, RawText, Regexp, Date +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, RawText, Regexp, Date from weboob.capabilities import NotAvailable from weboob.capabilities.bank import Account, Investment, Loan from weboob.capabilities.profile import Person diff --git a/modules/fortuneo/pages/compat/__init__.py b/modules/fortuneo/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/fortuneo/pages/compat/weboob_browser_filters_standard.py b/modules/fortuneo/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/fortuneo/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/fortuneo/pages/login.py b/modules/fortuneo/pages/login.py index 3b177a59be..e034cf49cb 100644 --- a/modules/fortuneo/pages/login.py +++ b/modules/fortuneo/pages/login.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.exceptions import BrowserUnavailable diff --git a/modules/fortuneo/pages/transfer.py b/modules/fortuneo/pages/transfer.py index 85170e1673..60a12e0a57 100644 --- a/modules/fortuneo/pages/transfer.py +++ b/modules/fortuneo/pages/transfer.py @@ -24,7 +24,7 @@ from weboob.browser.pages import HTMLPage, PartialHTMLPage, LoggedPage from weboob.browser.elements import method, ListElement, ItemElement, SkipItem -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Date, Regexp, CleanDecimal, Currency, Field, Env, ) from weboob.capabilities.bank import Recipient, Transfer, TransferBankError, AddRecipientBankError diff --git a/modules/francetelevisions/compat/__init__.py b/modules/francetelevisions/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/francetelevisions/compat/weboob_browser_filters_standard.py b/modules/francetelevisions/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/francetelevisions/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/francetelevisions/pages.py b/modules/francetelevisions/pages.py index 8ac50651c9..c29ce845d4 100644 --- a/modules/francetelevisions/pages.py +++ b/modules/francetelevisions/pages.py @@ -27,7 +27,7 @@ from weboob.browser.pages import HTMLPage, JsonPage from weboob.browser.elements import ItemElement, ListElement, method, DictElement -from weboob.browser.filters.standard import CleanText, Regexp, Format, Field, Env +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Format, Field, Env from weboob.browser.filters.html import CleanHTML from weboob.browser.filters.json import Dict diff --git a/modules/freemobile/pages/compat/__init__.py b/modules/freemobile/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/freemobile/pages/compat/weboob_browser_filters_standard.py b/modules/freemobile/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/freemobile/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/freemobile/pages/history.py b/modules/freemobile/pages/history.py index ab890caa2f..6878af25ad 100644 --- a/modules/freemobile/pages/history.py +++ b/modules/freemobile/pages/history.py @@ -24,7 +24,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Date, CleanText, Filter,\ +from .compat.weboob_browser_filters_standard import Date, CleanText, Filter,\ CleanDecimal, Currency, Regexp, Field, DateTime, Format, Env from weboob.browser.filters.html import AbsoluteLink, Attr from weboob.capabilities.bill import DocumentTypes, Detail, Bill diff --git a/modules/freemobile/pages/homepage.py b/modules/freemobile/pages/homepage.py index 5117d82c8d..adabe17d3f 100644 --- a/modules/freemobile/pages/homepage.py +++ b/modules/freemobile/pages/homepage.py @@ -20,7 +20,7 @@ from .history import BadUTF8Page from weboob.capabilities.bill import Subscription from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Field, Format +from .compat.weboob_browser_filters_standard import CleanText, Field, Format class HomePage(BadUTF8Page): diff --git a/modules/freemobile/pages/profile.py b/modules/freemobile/pages/profile.py index 999a4a4deb..613b06198e 100644 --- a/modules/freemobile/pages/profile.py +++ b/modules/freemobile/pages/profile.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.capabilities.profile import Profile -from weboob.browser.filters.standard import CleanText, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Regexp class ProfilePage(LoggedPage, HTMLPage): diff --git a/modules/freeteknomusic/compat/__init__.py b/modules/freeteknomusic/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/freeteknomusic/compat/weboob_browser_filters_standard.py b/modules/freeteknomusic/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/freeteknomusic/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/freeteknomusic/pages.py b/modules/freeteknomusic/pages.py index 7416392aa7..619317eda7 100644 --- a/modules/freeteknomusic/pages.py +++ b/modules/freeteknomusic/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Field, Decode +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Field, Decode from weboob.browser.filters.html import AbsoluteLink from weboob.capabilities.collection import Collection from weboob.capabilities.audio import BaseAudio diff --git a/modules/funmooc/compat/__init__.py b/modules/funmooc/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/funmooc/compat/weboob_browser_filters_standard.py b/modules/funmooc/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/funmooc/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/funmooc/pages.py b/modules/funmooc/pages.py index 840347e21b..3972906e1c 100644 --- a/modules/funmooc/pages.py +++ b/modules/funmooc/pages.py @@ -26,7 +26,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, ListElement, ItemElement, SkipItem from weboob.capabilities.collection import Collection -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class PageLogin(HTMLPage): diff --git a/modules/genericnewspaper/compat/weboob_browser_filters_standard.py b/modules/genericnewspaper/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/genericnewspaper/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/genericnewspaper/pages.py b/modules/genericnewspaper/pages.py index 6bd10c1876..acdfa8567c 100644 --- a/modules/genericnewspaper/pages.py +++ b/modules/genericnewspaper/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.filters.html import XPath, XPathNotFound -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from lxml.etree import Comment diff --git a/modules/gmf/compat/__init__.py b/modules/gmf/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/gmf/compat/weboob_browser_filters_standard.py b/modules/gmf/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/gmf/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/gmf/pages.py b/modules/gmf/pages.py index f7d509f1cb..387d1caeb4 100644 --- a/modules/gmf/pages.py +++ b/modules/gmf/pages.py @@ -24,7 +24,7 @@ from weboob.browser.pages import FormNotFound, HTMLPage, LoggedPage, XMLPage from weboob.browser.elements import ItemElement, method, ListElement, TableElement from weboob.capabilities.bank import Account, Investment -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Currency, Date, Eval, Field, Regexp, ) from weboob.browser.filters.html import Attr, TableCell diff --git a/modules/groupama/compat/__init__.py b/modules/groupama/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/groupama/compat/weboob_browser_filters_standard.py b/modules/groupama/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/groupama/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/groupama/pages.py b/modules/groupama/pages.py index ecbaeac010..eb58cf5bb2 100644 --- a/modules/groupama/pages.py +++ b/modules/groupama/pages.py @@ -27,7 +27,7 @@ from weboob.browser.pages import HTMLPage, pagination, LoggedPage, FormNotFound, JsonPage from weboob.browser.elements import method, TableElement, ItemElement -from weboob.browser.filters.standard import Env, CleanDecimal, CleanText, Date, Regexp, Eval, Field +from .compat.weboob_browser_filters_standard import Env, CleanDecimal, CleanText, Date, Regexp, Eval, Field from weboob.browser.filters.html import Attr, Link, TableCell from weboob.browser.filters.javascript import JSVar from weboob.capabilities.bank import Account, Investment diff --git a/modules/happn/browser.py b/modules/happn/browser.py index 88af5e5a58..56cca81963 100644 --- a/modules/happn/browser.py +++ b/modules/happn/browser.py @@ -23,7 +23,7 @@ from weboob.browser.browsers import DomainBrowser from weboob.browser.profiles import IPhone from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.exceptions import BrowserIncorrectPassword, ParseError from weboob.tools.json import json diff --git a/modules/happn/compat/weboob_browser_filters_standard.py b/modules/happn/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/happn/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/hds/compat/__init__.py b/modules/hds/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/hds/compat/weboob_browser_filters_standard.py b/modules/hds/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/hds/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/hds/pages.py b/modules/hds/pages.py index 225c5b134d..43d94b0483 100644 --- a/modules/hds/pages.py +++ b/modules/hds/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import method, ListElement, ItemElement -from weboob.browser.filters.standard import CleanText, Regexp, Date, Env, Filter +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Date, Env, Filter from weboob.browser.filters.html import XPath, Link diff --git a/modules/hsbc/browser.py b/modules/hsbc/browser.py index 9e1c2c2443..66be84e87b 100644 --- a/modules/hsbc/browser.py +++ b/modules/hsbc/browser.py @@ -20,7 +20,6 @@ from __future__ import unicode_literals import re -import ssl from datetime import timedelta, date from lxml.etree import XMLSyntaxError from collections import OrderedDict @@ -132,14 +131,6 @@ def __init__(self, username, password, secret, *args, **kwargs): def load_state(self, state): return - def prepare_request(self, req): - preq = super(HSBC, self).prepare_request(req) - - conn = self.session.adapters['https://'].get_connection(preq.url) - conn.ssl_version = ssl.PROTOCOL_TLSv1 - - return preq - def do_login(self): self.session.cookies.clear() diff --git a/modules/hsbc/pages/account_pages.py b/modules/hsbc/pages/account_pages.py index f923b66f69..4cef4ab322 100644 --- a/modules/hsbc/pages/account_pages.py +++ b/modules/hsbc/pages/account_pages.py @@ -28,7 +28,7 @@ from weboob.exceptions import BrowserIncorrectPassword, BrowserUnavailable, ActionNeeded from weboob.browser.elements import ListElement, ItemElement, method, TableElement from weboob.browser.pages import HTMLPage, pagination, LoggedPage -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( Filter, Env, CleanText, CleanDecimal, Field, DateGuesser, Regexp, Currency, Format, Date ) from weboob.browser.filters.html import AbsoluteLink, TableCell diff --git a/modules/hsbc/pages/compat/__init__.py b/modules/hsbc/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/hsbc/pages/compat/weboob_browser_filters_standard.py b/modules/hsbc/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/hsbc/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/hsbc/pages/investments.py b/modules/hsbc/pages/investments.py index 63147b3d73..66a7276dcb 100644 --- a/modules/hsbc/pages/investments.py +++ b/modules/hsbc/pages/investments.py @@ -13,7 +13,7 @@ from weboob.browser.elements import ItemElement, TableElement, DictElement, method from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Regexp, Currency, Field, Env, ) from weboob.browser.filters.html import TableCell, Link diff --git a/modules/hsbc/pages/landing_pages.py b/modules/hsbc/pages/landing_pages.py index 0b1c2856cf..907660c470 100644 --- a/modules/hsbc/pages/landing_pages.py +++ b/modules/hsbc/pages/landing_pages.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals from weboob.browser.pages import HTMLPage, LoggedPage -from weboob.browser.filters.standard import CleanText, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Regexp from weboob.browser.filters.html import Link diff --git a/modules/hsbc/pages/life_insurances.py b/modules/hsbc/pages/life_insurances.py index 49ab713c89..97c8e26640 100644 --- a/modules/hsbc/pages/life_insurances.py +++ b/modules/hsbc/pages/life_insurances.py @@ -10,7 +10,7 @@ from weboob.browser.elements import TableElement, ItemElement, method from weboob.browser.pages import HTMLPage, LoggedPage, FormNotFound -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Field, Regexp, Eval, Date ) from weboob.browser.filters.html import Link, XPathNotFound, TableCell diff --git a/modules/hybride/compat/__init__.py b/modules/hybride/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/hybride/compat/weboob_browser_filters_standard.py b/modules/hybride/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/hybride/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/hybride/pages.py b/modules/hybride/pages.py index 997ac6b834..c9b51420f3 100644 --- a/modules/hybride/pages.py +++ b/modules/hybride/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Filter, CleanText, Env, Format, BrowserURL, Regexp, Decode +from .compat.weboob_browser_filters_standard import Filter, CleanText, Env, Format, BrowserURL, Regexp, Decode from weboob.browser.filters.html import CleanHTML from weboob.browser.filters.html import Link diff --git a/modules/ilmatieteenlaitos/compat/__init__.py b/modules/ilmatieteenlaitos/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ilmatieteenlaitos/compat/weboob_browser_filters_standard.py b/modules/ilmatieteenlaitos/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ilmatieteenlaitos/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ilmatieteenlaitos/pages.py b/modules/ilmatieteenlaitos/pages.py index ad8390357c..67acf1d18f 100644 --- a/modules/ilmatieteenlaitos/pages.py +++ b/modules/ilmatieteenlaitos/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.capabilities.weather import Forecast, Current, City, Temperature from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import Filter, CleanText +from .compat.weboob_browser_filters_standard import Filter, CleanText class Id(Filter): diff --git a/modules/ina/compat/__init__.py b/modules/ina/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ina/compat/weboob_browser_filters_standard.py b/modules/ina/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ina/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ina/pages.py b/modules/ina/pages.py index a79907f5db..0e174105dc 100644 --- a/modules/ina/pages.py +++ b/modules/ina/pages.py @@ -24,7 +24,7 @@ from weboob.browser.pages import JsonPage, HTMLPage, XMLPage, pagination from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Duration, Date, BrowserURL, Env +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Duration, Date, BrowserURL, Env from weboob.capabilities.audio import BaseAudio from weboob.capabilities.video import BaseVideo diff --git a/modules/indeed/compat/__init__.py b/modules/indeed/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/indeed/compat/weboob_browser_filters_standard.py b/modules/indeed/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/indeed/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/indeed/pages.py b/modules/indeed/pages.py index 00efd00786..68eba2a64d 100644 --- a/modules/indeed/pages.py +++ b/modules/indeed/pages.py @@ -21,7 +21,7 @@ import re from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import Filter, CleanText, Regexp, Format, Env +from .compat.weboob_browser_filters_standard import Filter, CleanText, Regexp, Format, Env from weboob.browser.filters.html import CleanHTML, Attr from weboob.capabilities.job import BaseJobAdvert diff --git a/modules/infomaniak/compat/__init__.py b/modules/infomaniak/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/infomaniak/compat/weboob_browser_filters_standard.py b/modules/infomaniak/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/infomaniak/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/infomaniak/pages.py b/modules/infomaniak/pages.py index 91dac5ac65..9e4ebd144f 100644 --- a/modules/infomaniak/pages.py +++ b/modules/infomaniak/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import LoggedPage, JsonPage from weboob.browser.elements import ItemElement, method, DictElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanDecimal, Env, Regexp, Format, Currency, Field, Eval, ) from weboob.browser.filters.json import Dict diff --git a/modules/ing/api/accounts_page.py b/modules/ing/api/accounts_page.py index 20f4367cec..bf04caad73 100644 --- a/modules/ing/api/accounts_page.py +++ b/modules/ing/api/accounts_page.py @@ -24,7 +24,7 @@ from weboob.browser.pages import LoggedPage, JsonPage from weboob.browser.elements import method, DictElement, ItemElement from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Date, Eval, Lower, Format, Field, Map, Upper, ) from weboob.capabilities.bank import Account diff --git a/modules/ing/api/compat/weboob_browser_filters_standard.py b/modules/ing/api/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ing/api/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ing/api/profile_page.py b/modules/ing/api/profile_page.py index 4472f386bf..21a8661c42 100644 --- a/modules/ing/api/profile_page.py +++ b/modules/ing/api/profile_page.py @@ -21,7 +21,7 @@ from weboob.browser.pages import LoggedPage, JsonPage from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanText, Format +from .compat.weboob_browser_filters_standard import CleanText, Format from weboob.browser.elements import ItemElement, method from weboob.capabilities.profile import Profile from weboob.capabilities.base import NotAvailable diff --git a/modules/ing/api/transfer_page.py b/modules/ing/api/transfer_page.py index c9349bca10..c3dfb0def0 100644 --- a/modules/ing/api/transfer_page.py +++ b/modules/ing/api/transfer_page.py @@ -25,7 +25,7 @@ from weboob.browser.pages import LoggedPage, JsonPage from weboob.browser.elements import method, DictElement, ItemElement from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import Env, Field, Date +from .compat.weboob_browser_filters_standard import Env, Field, Date from weboob.capabilities.bank import Recipient from .login import INGVirtKeyboard diff --git a/modules/ing/pages/accounts_list.py b/modules/ing/pages/accounts_list.py index 3e5fbd5a02..416969c81e 100644 --- a/modules/ing/pages/accounts_list.py +++ b/modules/ing/pages/accounts_list.py @@ -28,7 +28,7 @@ from weboob.capabilities.profile import Person from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage from weboob.browser.elements import ListElement, TableElement, ItemElement, method, DataError -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Eval, Filter, Field, MultiFilter, Date, Lower, Async, AsyncLoad, Format, Env, Regexp, diff --git a/modules/ing/pages/bills.py b/modules/ing/pages/bills.py index 41fd423380..0f24474da9 100644 --- a/modules/ing/pages/bills.py +++ b/modules/ing/pages/bills.py @@ -21,7 +21,7 @@ from weboob.capabilities.bill import DocumentTypes, Bill, Subscription from weboob.browser.pages import HTMLPage, LoggedPage, pagination, Form -from weboob.browser.filters.standard import Filter, CleanText, Format, Field, Env, Date +from .compat.weboob_browser_filters_standard import Filter, CleanText, Format, Field, Env, Date from weboob.browser.filters.html import Attr from weboob.browser.elements import ListElement, ItemElement, method from weboob.tools.date import parse_french_date diff --git a/modules/ing/pages/compat/weboob_browser_filters_standard.py b/modules/ing/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ing/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ing/pages/compat/weboob_tools_captcha_virtkeyboard.py b/modules/ing/pages/compat/weboob_tools_captcha_virtkeyboard.py deleted file mode 100644 index 3f29ddc260..0000000000 --- a/modules/ing/pages/compat/weboob_tools_captcha_virtkeyboard.py +++ /dev/null @@ -1,196 +0,0 @@ - -import weboob.tools.captcha.virtkeyboard as OLD - -# can't import *, __all__ is incomplete... -for attr in dir(OLD): - globals()[attr] = getattr(OLD, attr) - - -try: - __all__ = OLD.__all__ -except AttributeError: - pass - - -class SimpleVirtualKeyboard(object): - """Handle a virtual keyboard where "keys" are distributed on a simple grid. - - Parameters: - :param cols: Column count of the grid - :type cols: int - :param rows: Row count of the grid - :type rows: int - :param image: File-like object to be used as data source - :type image: file - :param convert: Mode to which convert color of pixels, see - :meth:`Image.Image.convert` for more information - :param matching_symbols: symbol that match all case of image grid from left to right and top - to down, European reading way. - :type matching_symbols: iterable - :param matching_symbols_coords: dict mapping matching website symbols to their image coords - (x0, y0, x1, y1) on grid image from left to right and top to - down, European reading way. It's not symbols in the image. - :type matching_symbols_coords: dict[str:4-tuple(int)] - :param browser: Browser of weboob session. - Allow to dump tiles files in same directory than session folder - :type browser: obj(Browser) - - Attributes: - :attribute codesep: Output separator between matching symbols - :type codesep: str - :param margin: Useless image pixel to cut. - See :func:`cut_margin`. - :type margin: 4-tuple(int), same as HTML margin: (top, right, bottom, left). - or 2-tuple(int), (top = bottom, right = left), - or int, top = right = bottom = left - :attribute tile_margin: Useless tile pixel to cut. - See :func:`cut_margin`. - :attribute symbols: Association table between image symbols and md5s - :type symbols: dict[str:str] or dict[str:n-tuple(str)] - :attribute convert: Mode to which convert color of pixels, see - :meth:`Image.Image.convert` for more information - :attribute alter: Allow custom main image alteration. Then overwrite :func:`alter_image`. - :type alter: boolean - """ - - codesep = '' - margin = None - tile_margin = None - symbols = None - convert = None - - def __init__(self, file, cols, rows, matching_symbols=None, matching_symbols_coords=None, browser=None): - self.cols = cols - self.rows = rows - - # Needed even if init is overwrite - self.path = self.build_path(browser) - - # Get self.image - self.load_image(file, self.margin, self.convert) - - # Get self.tiles - self.get_tiles( matching_symbols=matching_symbols, - matching_symbols_coords=matching_symbols_coords) - - # Tiles processing - self.cut_tiles(self.tile_margin) - self.hash_md5_tiles() - - def build_path(self, browser=None): - if browser and browser.responses_dirname: - return browser.responses_dirname - else: - return tempfile.mkdtemp(prefix='weboob_session_') - - def load_image(self, file, margin=None, convert=None): - self.image = Image.open(file) - # Resize image if margin is given - if margin: - self.image = self.cut_margin(self.image, margin) - if convert: - self.image = self.image.convert(convert) - # Give possibility to alter image before get tiles, overwrite :func:`alter_image`. - self.alter_image() - self.width, self.height = self.image.size - - def alter_image(self): - pass - - def cut_margin(self, image, margin): - width, height = image.size - - # Verify the magin value format - if type(margin) is int: - margin = (margin, margin, margin, margin) - elif len(margin) == 2: - margin = (margin[0], margin[1], margin[0], margin[1]) - elif len(margin) == 4: - margin = margin - else: - assert (len(margin) == 3) & (len(margin) > 4), \ - "Margin format is wrong." - - assert ((margin[0] + margin[2]) < height) & ((margin[1] + margin[3]) < width), \ - "Margin is too high, there is not enough pixel to cut." - - image = image.crop((0 + margin[3], - 0 + margin[0], - width - margin[1], - height - margin[2] - )) - return image - - def get_tiles(self, matching_symbols=None, matching_symbols_coords=None): - self.tiles = [] - - # Tiles coords are given - if matching_symbols_coords: - for matching_symbol in matching_symbols_coords: - self.tiles.append(Tile( matching_symbol=matching_symbol, - coords=matching_symbols_coords[matching_symbol] - )) - return - - assert (not self.width%self.cols) & (not self.height%self.rows), \ - "Image width and height are not multiple of cols and rows. Please resize image with attribute `margin`." - - # Tiles coords aren't given, calculate them - self.tileW = self.width // self.cols - self.tileH = self.height // self.rows - - # Matching symbols aren't given, default value is range(columns*rows) - if not matching_symbols: - matching_symbols = ['%s' % i for i in range(self.cols*self.rows)] - - assert len(matching_symbols) == (self.cols*self.rows), \ - "Number of website matching symbols is not equal to the number of cases on the image." - - # Calculate tiles coords for each matching symbol from 1-dimension to 2-dimensions - for index, matching_symbol in enumerate(matching_symbols): - coords = self.get_tile_coords_in_grid(index) - self.tiles.append(Tile(matching_symbol=matching_symbol, coords=coords)) - - def get_tile_coords_in_grid(self, case_index): - # Get the top left pixel coords of the tile - x0 = (case_index % self.cols) * self.tileW - y0 = (case_index // self.cols) * self.tileH - - # Get the bottom right coords of the tile - x1 = x0 + self.tileW - y1 = y0 + self.tileH - - coords = (x0, y0, x1, y1) - return(coords) - - def cut_tiles(self, tile_margin=None): - for tile in self.tiles: - tile.image = self.image.crop(tile.coords) - - # Resize tile if margin is given - if tile_margin: - for tile in self.tiles: - tile.image = self.cut_margin(tile.image, tile_margin) - - def hash_md5_tiles(self): - for tile in self.tiles: - tile.md5 = hashlib.md5(tile.image.tobytes()).hexdigest() - - def dump_tiles(self, path): - for tile in self.tiles: - tile.image.save('{}/{}.png'.format(path, tile.md5)) - - def get_string_code(self, password): - word = [] - - for digit in password: - for tile in self.tiles: - if tile.md5 in self.symbols[digit]: - word.append(tile.matching_symbol) - break - else: - # Dump file only if the symbol is not found - self.dump_tiles(self.path) - raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s" - % (digit, self.path)) - return self.codesep.join(word) diff --git a/modules/ing/pages/login.py b/modules/ing/pages/login.py index d0879f5b45..1be8b63880 100644 --- a/modules/ing/pages/login.py +++ b/modules/ing/pages/login.py @@ -23,7 +23,7 @@ from .compat.weboob_tools_captcha_virtkeyboard import VirtKeyboard from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.filters.html import Attr -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class INGVirtKeyboard(VirtKeyboard): diff --git a/modules/ing/pages/titre.py b/modules/ing/pages/titre.py index bb02e8b047..9278d9e62d 100644 --- a/modules/ing/pages/titre.py +++ b/modules/ing/pages/titre.py @@ -26,7 +26,7 @@ from weboob.capabilities.bank import Investment from weboob.browser.pages import RawPage, HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, TableElement, ItemElement, method -from weboob.browser.filters.standard import CleanDecimal, CleanText, Date, Regexp, Env +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Date, Regexp, Env from weboob.browser.filters.html import Link, Attr, TableCell from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.capabilities.bank.investments import create_french_liquidity diff --git a/modules/ing/pages/transfer.py b/modules/ing/pages/transfer.py index 452c6a92af..8864b44148 100644 --- a/modules/ing/pages/transfer.py +++ b/modules/ing/pages/transfer.py @@ -23,7 +23,7 @@ from weboob.capabilities import NotAvailable from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Env +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Env from weboob.browser.filters.html import Attr from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.capabilities.bank.iban import is_iban_valid diff --git a/modules/ing/web/accounts_list.py b/modules/ing/web/accounts_list.py index 01ed8c84b4..1bfd94eef4 100644 --- a/modules/ing/web/accounts_list.py +++ b/modules/ing/web/accounts_list.py @@ -28,7 +28,7 @@ from weboob.capabilities.profile import Person from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage from weboob.browser.elements import ListElement, TableElement, ItemElement, method, DataError -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Eval, Filter, Field, MultiFilter, Date, Lower, Async, AsyncLoad, Format, Env, Regexp, diff --git a/modules/ing/web/bills.py b/modules/ing/web/bills.py index 0a2dcbea69..9896e285fb 100644 --- a/modules/ing/web/bills.py +++ b/modules/ing/web/bills.py @@ -21,7 +21,7 @@ from weboob.capabilities.bill import DocumentTypes, Bill, Subscription from weboob.browser.pages import HTMLPage, LoggedPage, pagination, Form -from weboob.browser.filters.standard import Filter, CleanText, Format, Field, Env, Date +from .compat.weboob_browser_filters_standard import Filter, CleanText, Format, Field, Env, Date from weboob.browser.filters.html import Attr from weboob.browser.elements import ListElement, ItemElement, method from weboob.tools.date import parse_french_date diff --git a/modules/ing/web/compat/__init__.py b/modules/ing/web/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ing/web/compat/weboob_browser_filters_standard.py b/modules/ing/web/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ing/web/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ing/web/login.py b/modules/ing/web/login.py index 4d0234009d..e55dc1b07b 100644 --- a/modules/ing/web/login.py +++ b/modules/ing/web/login.py @@ -20,7 +20,7 @@ from weboob.exceptions import ActionNeeded from weboob.browser.pages import HTMLPage, LoggedPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class ActionNeededPage(HTMLPage): diff --git a/modules/ing/web/titre.py b/modules/ing/web/titre.py index a1fb39e4b1..ffd7a20c9d 100644 --- a/modules/ing/web/titre.py +++ b/modules/ing/web/titre.py @@ -26,7 +26,7 @@ from weboob.capabilities.bank import Investment from weboob.browser.pages import RawPage, HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, TableElement, ItemElement, method -from weboob.browser.filters.standard import CleanDecimal, CleanText, Date, Regexp, Env +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Date, Regexp, Env from weboob.browser.filters.html import Link, Attr, TableCell from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.capabilities.bank.investments import create_french_liquidity diff --git a/modules/ipinfodb/compat/__init__.py b/modules/ipinfodb/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ipinfodb/compat/weboob_browser_filters_standard.py b/modules/ipinfodb/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ipinfodb/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ipinfodb/pages.py b/modules/ipinfodb/pages.py index 0a81526f2a..9808c53d81 100644 --- a/modules/ipinfodb/pages.py +++ b/modules/ipinfodb/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, method from weboob.capabilities.geolocip import IpLocation -from weboob.browser.filters.standard import Regexp, CleanText, Type +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Type from weboob.capabilities.base import NotAvailable diff --git a/modules/journaldesfemmes/compat/__init__.py b/modules/journaldesfemmes/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/journaldesfemmes/compat/weboob_browser_filters_standard.py b/modules/journaldesfemmes/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/journaldesfemmes/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/journaldesfemmes/pages.py b/modules/journaldesfemmes/pages.py index c0b3a36f84..b7e7948807 100644 --- a/modules/journaldesfemmes/pages.py +++ b/modules/journaldesfemmes/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Env, Regexp, Eval, ) from weboob.browser.filters.html import Attr, Link, XPath diff --git a/modules/kickass/compat/__init__.py b/modules/kickass/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/kickass/compat/weboob_browser_filters_standard.py b/modules/kickass/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/kickass/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/kickass/pages.py b/modules/kickass/pages.py index 5a17debdf7..0290f3d2df 100644 --- a/modules/kickass/pages.py +++ b/modules/kickass/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText, Type +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Type class SearchPage(HTMLPage): diff --git a/modules/lacentrale/compat/__init__.py b/modules/lacentrale/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lacentrale/compat/weboob_browser_filters_standard.py b/modules/lacentrale/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lacentrale/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lacentrale/pages.py b/modules/lacentrale/pages.py index 05a8937252..483e4fd438 100644 --- a/modules/lacentrale/pages.py +++ b/modules/lacentrale/pages.py @@ -20,7 +20,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage, pagination -from weboob.browser.filters.standard import CleanText, Regexp, CleanDecimal, Format, Env, BrowserURL +from .compat.weboob_browser_filters_standard import CleanText, Regexp, CleanDecimal, Format, Env, BrowserURL from weboob.browser.filters.javascript import JSVar from weboob.browser.filters.html import Link from weboob.capabilities.pricecomparison import Price, Shop diff --git a/modules/lameteoagricole/compat/__init__.py b/modules/lameteoagricole/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lameteoagricole/compat/weboob_browser_filters_standard.py b/modules/lameteoagricole/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lameteoagricole/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lameteoagricole/pages.py b/modules/lameteoagricole/pages.py index 6281b1e20d..aa29922053 100644 --- a/modules/lameteoagricole/pages.py +++ b/modules/lameteoagricole/pages.py @@ -22,7 +22,7 @@ from datetime import date, time, datetime, timedelta from weboob.browser.elements import method, ListElement, ItemElement -from weboob.browser.filters.standard import CleanText, Field +from .compat.weboob_browser_filters_standard import CleanText, Field from weboob.browser.pages import HTMLPage from weboob.capabilities.weather import City, Forecast, Temperature, Current, Direction from weboob.tools.compat import quote diff --git a/modules/lampiris/compat/__init__.py b/modules/lampiris/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lampiris/compat/weboob_browser_filters_standard.py b/modules/lampiris/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lampiris/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lampiris/pages.py b/modules/lampiris/pages.py index 5e46c80132..d69af4c47d 100644 --- a/modules/lampiris/pages.py +++ b/modules/lampiris/pages.py @@ -22,7 +22,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.filters.html import Attr, CleanHTML, Link, XPathNotFound -from weboob.browser.filters.standard import CleanDecimal, CleanText, Date, Format +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Date, Format from weboob.browser.pages import HTMLPage from weboob.capabilities.base import NotAvailable, Currency from weboob.capabilities.bill import Bill, Subscription diff --git a/modules/larousse/compat/__init__.py b/modules/larousse/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/larousse/compat/weboob_browser_filters_standard.py b/modules/larousse/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/larousse/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/larousse/pages.py b/modules/larousse/pages.py index 4698364d84..fbf47ba683 100644 --- a/modules/larousse/pages.py +++ b/modules/larousse/pages.py @@ -23,7 +23,7 @@ from weboob.capabilities.translate import Translation from weboob.browser.elements import method, ListElement, ItemElement -from weboob.browser.filters.standard import Env, CleanText +from .compat.weboob_browser_filters_standard import Env, CleanText from weboob.browser.pages import HTMLPage CODES = { diff --git a/modules/lcl/browser.py b/modules/lcl/browser.py index 7813ca0daf..bd61755104 100644 --- a/modules/lcl/browser.py +++ b/modules/lcl/browser.py @@ -49,7 +49,7 @@ class LCLBrowser(LoginBrowser, StatesMixin): BASEURL = 'https://particuliers.secure.lcl.fr' STATE_DURATION = 15 - login = URL('/outil/UAUT/Authentication/authenticate', + login = URL('/outil/UAUT\?from=/outil/UWHO/Accueil/', '/outil/UAUT\?from=.*', '/outil/UWER/Accueil/majicER', '/outil/UWER/Enregistrement/forwardAcc', @@ -153,7 +153,8 @@ def do_login(self): # we force the browser to go to login page so it's work even # if the session expire - self.login.go() + # Must set the referer to avoid redirection to the home page + self.login.go(headers={"Referer": "https://www.lcl.fr/"}) if not self.page.login(self.username, self.password) or \ (self.login.is_here() and self.page.is_error()): diff --git a/modules/lcl/compat/weboob_browser_filters_standard.py b/modules/lcl/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lcl/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lcl/enterprise/compat/__init__.py b/modules/lcl/enterprise/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lcl/enterprise/compat/weboob_browser_filters_standard.py b/modules/lcl/enterprise/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lcl/enterprise/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lcl/enterprise/pages.py b/modules/lcl/enterprise/pages.py index 147ada6e5c..a1579de84e 100644 --- a/modules/lcl/enterprise/pages.py +++ b/modules/lcl/enterprise/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, ItemElement, TableElement, method -from weboob.browser.filters.standard import CleanText, Date, CleanDecimal, Env +from .compat.weboob_browser_filters_standard import CleanText, Date, CleanDecimal, Env from weboob.browser.filters.html import Link, TableCell from weboob.capabilities.bank import Account from weboob.capabilities.profile import Profile diff --git a/modules/lcl/pages.py b/modules/lcl/pages.py index 1e3526d951..28379ea1a9 100644 --- a/modules/lcl/pages.py +++ b/modules/lcl/pages.py @@ -40,7 +40,7 @@ from weboob.browser.exceptions import ServerError from weboob.browser.pages import LoggedPage, HTMLPage, JsonPage, FormNotFound, pagination from weboob.browser.filters.html import Attr, Link, TableCell, AttributeNotFound -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Field, Regexp, Format, Date, CleanDecimal, Map, AsyncLoad, Async, Env, Slugify, BrowserURL, Eval, ) from weboob.browser.filters.json import Dict diff --git a/modules/ldlc/compat/__init__.py b/modules/ldlc/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ldlc/compat/weboob_browser_filters_standard.py b/modules/ldlc/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ldlc/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ldlc/pages.py b/modules/ldlc/pages.py index 9e0003bf8c..977a0ab343 100644 --- a/modules/ldlc/pages.py +++ b/modules/ldlc/pages.py @@ -20,7 +20,7 @@ from __future__ import unicode_literals from weboob.browser.pages import HTMLPage, LoggedPage -from weboob.browser.filters.standard import CleanDecimal, CleanText, Env, Format, QueryValue, TableCell, Currency +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Env, Format, QueryValue, TableCell, Currency from weboob.browser.elements import ListElement, ItemElement, method, TableElement from weboob.browser.filters.html import Attr from weboob.capabilities.bill import Bill, Subscription diff --git a/modules/leboncoin/compat/__init__.py b/modules/leboncoin/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/leboncoin/compat/weboob_browser_filters_standard.py b/modules/leboncoin/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/leboncoin/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/leboncoin/pages.py b/modules/leboncoin/pages.py index 9005f464ee..7f09fde875 100644 --- a/modules/leboncoin/pages.py +++ b/modules/leboncoin/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, JsonPage, pagination from weboob.browser.elements import ItemElement, ListElement, method, DictElement from weboob.capabilities.base import Currency as BaseCurrency -from weboob.browser.filters.standard import (CleanText, CleanDecimal, _Filter, +from .compat.weboob_browser_filters_standard import (CleanText, CleanDecimal, _Filter, Env, DateTime, Format) from weboob.browser.filters.json import Dict from weboob.capabilities.housing import (City, Housing, HousingPhoto, diff --git a/modules/lefigaro/compat/__init__.py b/modules/lefigaro/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lefigaro/compat/weboob_browser_filters_standard.py b/modules/lefigaro/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lefigaro/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lefigaro/pages.py b/modules/lefigaro/pages.py index 483abd12a8..8867e73ec9 100644 --- a/modules/lefigaro/pages.py +++ b/modules/lefigaro/pages.py @@ -19,7 +19,7 @@ # along with this weboob module. If not, see . from weboob.browser.pages import AbstractPage from weboob.browser.filters.html import CSS -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class ArticlePage(AbstractPage): diff --git a/modules/liberation/compat/__init__.py b/modules/liberation/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/liberation/compat/weboob_browser_filters_standard.py b/modules/liberation/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/liberation/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/liberation/pages.py b/modules/liberation/pages.py index 79df9bfdad..09012ee172 100644 --- a/modules/liberation/pages.py +++ b/modules/liberation/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import AbstractPage from weboob.browser.filters.html import XPathNotFound, CSS -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class ArticlePage(AbstractPage): diff --git a/modules/limetorrents/compat/__init__.py b/modules/limetorrents/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/limetorrents/compat/weboob_browser_filters_standard.py b/modules/limetorrents/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/limetorrents/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/limetorrents/pages.py b/modules/limetorrents/pages.py index dc48030a58..b85487ab12 100644 --- a/modules/limetorrents/pages.py +++ b/modules/limetorrents/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage, pagination -from weboob.browser.filters.standard import Regexp, CleanText, CleanDecimal, Format +from .compat.weboob_browser_filters_standard import Regexp, CleanText, CleanDecimal, Format from weboob.browser.filters.html import AbsoluteLink diff --git a/modules/linebourse/api/compat/__init__.py b/modules/linebourse/api/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/linebourse/api/compat/weboob_browser_filters_standard.py b/modules/linebourse/api/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/linebourse/api/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/linebourse/api/pages.py b/modules/linebourse/api/pages.py index b0ec69defa..9f26d7660f 100644 --- a/modules/linebourse/api/pages.py +++ b/modules/linebourse/api/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import method, DictElement, ItemElement from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( Date, CleanDecimal, Eval, Field, Env, Regexp, Format, ) from weboob.browser.pages import JsonPage, HTMLPage, LoggedPage diff --git a/modules/linebourse/compat/__init__.py b/modules/linebourse/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/linebourse/compat/weboob_browser_filters_standard.py b/modules/linebourse/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/linebourse/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/linebourse/pages.py b/modules/linebourse/pages.py index 679bcaf0ec..c1fdf50e2d 100644 --- a/modules/linebourse/pages.py +++ b/modules/linebourse/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, TableElement, ItemElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Date, CleanDecimal, Regexp, Eval, Field ) from weboob.browser.filters.html import TableCell diff --git a/modules/linuxjobs/compat/__init__.py b/modules/linuxjobs/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/linuxjobs/compat/weboob_browser_filters_standard.py b/modules/linuxjobs/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/linuxjobs/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/linuxjobs/pages.py b/modules/linuxjobs/pages.py index 5545be5cd7..c5c1bc6ef5 100644 --- a/modules/linuxjobs/pages.py +++ b/modules/linuxjobs/pages.py @@ -21,7 +21,7 @@ from weboob.capabilities.job import BaseJobAdvert from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Regexp, CleanText, Date, Env, BrowserURL +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Date, Env, BrowserURL from weboob.browser.filters.html import Link, CleanHTML from weboob.tools.date import parse_french_date diff --git a/modules/logicimmo/compat/__init__.py b/modules/logicimmo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/logicimmo/compat/weboob_browser_filters_standard.py b/modules/logicimmo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/logicimmo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/logicimmo/pages.py b/modules/logicimmo/pages.py index 37edf68c46..9d147977dd 100644 --- a/modules/logicimmo/pages.py +++ b/modules/logicimmo/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, JsonPage from weboob.browser.elements import ItemElement, ListElement, DictElement, method from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import (Currency, Format, CleanText, +from .compat.weboob_browser_filters_standard import (Currency, Format, CleanText, Regexp, CleanDecimal, Date, Env, BrowserURL) from weboob.browser.filters.html import Attr, XPath, CleanHTML diff --git a/modules/lolix/compat/__init__.py b/modules/lolix/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lolix/compat/weboob_browser_filters_standard.py b/modules/lolix/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lolix/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lolix/pages.py b/modules/lolix/pages.py index b394c12de1..7693c8c8af 100644 --- a/modules/lolix/pages.py +++ b/modules/lolix/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import TableElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Date, Env, BrowserURL, Join, Format +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Date, Env, BrowserURL, Join, Format from weboob.browser.filters.html import CleanHTML, TableCell from weboob.capabilities.job import BaseJobAdvert diff --git a/modules/lyricsdotcom/compat/__init__.py b/modules/lyricsdotcom/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lyricsdotcom/compat/weboob_browser_filters_standard.py b/modules/lyricsdotcom/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lyricsdotcom/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lyricsdotcom/pages.py b/modules/lyricsdotcom/pages.py index 3e60de6213..4b9b93f1e0 100644 --- a/modules/lyricsdotcom/pages.py +++ b/modules/lyricsdotcom/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText, Env, BrowserURL +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Env, BrowserURL from weboob.browser.filters.html import CleanHTML, XPath diff --git a/modules/lyricsmode/compat/__init__.py b/modules/lyricsmode/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lyricsmode/compat/weboob_browser_filters_standard.py b/modules/lyricsmode/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lyricsmode/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lyricsmode/pages.py b/modules/lyricsmode/pages.py index c7a3ee8b8c..655ef00aed 100644 --- a/modules/lyricsmode/pages.py +++ b/modules/lyricsmode/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText +from .compat.weboob_browser_filters_standard import Regexp, CleanText from weboob.browser.filters.html import CleanHTML diff --git a/modules/lyricsplanet/compat/__init__.py b/modules/lyricsplanet/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/lyricsplanet/compat/weboob_browser_filters_standard.py b/modules/lyricsplanet/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/lyricsplanet/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/lyricsplanet/pages.py b/modules/lyricsplanet/pages.py index 6c997b808b..5dbcc10c6d 100644 --- a/modules/lyricsplanet/pages.py +++ b/modules/lyricsplanet/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText +from .compat.weboob_browser_filters_standard import Regexp, CleanText from weboob.browser.filters.html import CleanHTML diff --git a/modules/manpower/compat/__init__.py b/modules/manpower/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/manpower/compat/weboob_browser_filters_standard.py b/modules/manpower/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/manpower/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/manpower/pages.py b/modules/manpower/pages.py index fd2744c690..e6a2a1c1bf 100644 --- a/modules/manpower/pages.py +++ b/modules/manpower/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Env, BrowserURL, Date, Format +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env, BrowserURL, Date, Format from weboob.browser.filters.html import CleanHTML from weboob.capabilities.job import BaseJobAdvert from weboob.capabilities.base import NotAvailable diff --git a/modules/mareeinfo/compat/__init__.py b/modules/mareeinfo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/mareeinfo/compat/weboob_browser_filters_standard.py b/modules/mareeinfo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/mareeinfo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/mareeinfo/pages.py b/modules/mareeinfo/pages.py index d7957aebef..123b57b624 100644 --- a/modules/mareeinfo/pages.py +++ b/modules/mareeinfo/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, DateTime, CleanDecimal, Regexp +from .compat.weboob_browser_filters_standard import CleanText, DateTime, CleanDecimal, Regexp from weboob.browser.filters.html import Link, XPath from weboob.capabilities.gauge import Gauge, GaugeMeasure, GaugeSensor from datetime import timedelta diff --git a/modules/marmiton/compat/__init__.py b/modules/marmiton/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/marmiton/compat/weboob_browser_filters_standard.py b/modules/marmiton/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/marmiton/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/marmiton/pages.py b/modules/marmiton/pages.py index 64797d2420..7d6ec24392 100644 --- a/modules/marmiton/pages.py +++ b/modules/marmiton/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Regexp, CleanText, Format, Env, CleanDecimal, Eval +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Format, Env, CleanDecimal, Eval from weboob.browser.filters.html import XPath from weboob.browser.filters.json import Dict from weboob.capabilities.recipe import Recipe, Comment diff --git a/modules/materielnet/compat/__init__.py b/modules/materielnet/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/materielnet/compat/weboob_browser_filters_standard.py b/modules/materielnet/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/materielnet/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/materielnet/pages.py b/modules/materielnet/pages.py index 36f0fb09ed..129b7582d3 100644 --- a/modules/materielnet/pages.py +++ b/modules/materielnet/pages.py @@ -22,7 +22,7 @@ import re from weboob.browser.pages import HTMLPage, LoggedPage, PartialHTMLPage -from weboob.browser.filters.standard import CleanText, CleanDecimal, Env, Format, Date, Async, Filter, Regexp, Field +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Env, Format, Date, Async, Filter, Regexp, Field from weboob.browser.elements import ListElement, ItemElement, method from weboob.browser.filters.html import Attr, Link from weboob.capabilities.bill import DocumentTypes, Bill, Subscription diff --git a/modules/meslieuxparis/compat/__init__.py b/modules/meslieuxparis/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/meslieuxparis/compat/weboob_browser_filters_standard.py b/modules/meslieuxparis/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/meslieuxparis/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/meslieuxparis/pages.py b/modules/meslieuxparis/pages.py index 3f193b1b3d..db9b724efd 100644 --- a/modules/meslieuxparis/pages.py +++ b/modules/meslieuxparis/pages.py @@ -23,7 +23,7 @@ from dateutil import rrule from weboob.browser.elements import method, ItemElement, DictElement -from weboob.browser.filters.standard import CleanText, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Regexp from weboob.browser.filters.json import Dict from weboob.browser.pages import JsonPage from weboob.capabilities.base import NotAvailable diff --git a/modules/meteofrance/compat/__init__.py b/modules/meteofrance/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/meteofrance/compat/weboob_browser_filters_standard.py b/modules/meteofrance/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/meteofrance/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/meteofrance/pages.py b/modules/meteofrance/pages.py index 7954d933ae..2c88b9b8ef 100644 --- a/modules/meteofrance/pages.py +++ b/modules/meteofrance/pages.py @@ -25,7 +25,7 @@ from weboob.capabilities.base import NotAvailable from weboob.capabilities.weather import Forecast, Current, City, Temperature from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, Format, Eval +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Regexp, Format, Eval class SearchCitiesPage(JsonPage): diff --git a/modules/minutes20/compat/__init__.py b/modules/minutes20/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/minutes20/compat/weboob_browser_filters_standard.py b/modules/minutes20/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/minutes20/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/minutes20/pages.py b/modules/minutes20/pages.py index c882938ca8..ee2ad9b2e2 100644 --- a/modules/minutes20/pages.py +++ b/modules/minutes20/pages.py @@ -20,7 +20,7 @@ # along with this weboob module. If not, see . from weboob.browser.pages import AbstractPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.browser.filters.html import CSS diff --git a/modules/monster/compat/__init__.py b/modules/monster/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/monster/compat/weboob_browser_filters_standard.py b/modules/monster/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/monster/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/monster/pages.py b/modules/monster/pages.py index bbe59009bb..9d2499aa3e 100644 --- a/modules/monster/pages.py +++ b/modules/monster/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Filter, Env, BrowserURL, Format, DateTime +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Filter, Env, BrowserURL, Format, DateTime from weboob.browser.filters.html import CleanHTML from weboob.capabilities.job import BaseJobAdvert from weboob.capabilities.base import NotAvailable diff --git a/modules/myedenred/browser.py b/modules/myedenred/browser.py index 696ffba9e3..3267f375cf 100644 --- a/modules/myedenred/browser.py +++ b/modules/myedenred/browser.py @@ -22,7 +22,7 @@ from weboob.browser import LoginBrowser, URL, need_login from weboob.exceptions import BrowserIncorrectPassword from weboob.tools.capabilities.bank.transactions import merge_iterators -from .pages import LoginPage, AccountsPage, TransactionsPage +from .pages import LoginPage, AccountsPage, AccountDetailsPage, TransactionsPage class MyedenredBrowser(LoginBrowser): @@ -31,6 +31,7 @@ class MyedenredBrowser(LoginBrowser): login = URL(r'/ctr\?Length=7', r'/ExtendedAccount/Logon', LoginPage) accounts = URL(r'/$', AccountsPage) + accounts_details = URL(r'/ExtendedHome/ProductLine\?benId=(?P\d+)', AccountDetailsPage) transactions = URL('/Card/TransactionSet', TransactionsPage) def __init__(self, *args, **kwargs): @@ -46,8 +47,11 @@ def do_login(self): raise BrowserIncorrectPassword @need_login - def get_accounts_list(self): - return self.accounts.stay_or_go().iter_accounts() + def iter_accounts(self): + for acc_id in self.accounts.stay_or_go().get_accounts_id(): + yield self.accounts_details.go(headers={'X-Requested-With': 'XMLHttpRequest'}, + token=acc_id).get_account() + @need_login def iter_history(self, account): diff --git a/modules/myedenred/compat/__init__.py b/modules/myedenred/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/myedenred/compat/weboob_browser_filters_standard.py b/modules/myedenred/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/myedenred/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/myedenred/module.py b/modules/myedenred/module.py index 256ff9ab18..e62cb3e2b5 100644 --- a/modules/myedenred/module.py +++ b/modules/myedenred/module.py @@ -47,7 +47,7 @@ def create_default_browser(self): return self.create_browser(self.config['login'].get(), self.config['password'].get()) def iter_accounts(self): - return self.browser.get_accounts_list() + return self.browser.iter_accounts() def get_account(self, id): return find_object(self.iter_accounts(), id=id, error=AccountNotFound) diff --git a/modules/myedenred/pages.py b/modules/myedenred/pages.py index 3372f2a574..e77b456131 100644 --- a/modules/myedenred/pages.py +++ b/modules/myedenred/pages.py @@ -20,9 +20,9 @@ from __future__ import unicode_literals -from weboob.browser.pages import HTMLPage, LoggedPage +from weboob.browser.pages import HTMLPage, PartialHTMLPage, LoggedPage from weboob.browser.elements import ItemElement, method, ListElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Regexp, DateGuesser, Field ) @@ -43,22 +43,26 @@ def get_error(self): class AccountsPage(LoggedPage, HTMLPage): + def get_accounts_id(self): + for e in self.doc.xpath('//ul[@id="navSideProducts"]//strong[contains(text(), "Restaurant")]/ancestor::li'): + yield e.attrib['id'].split('_')[-1] + + +class AccountDetailsPage(LoggedPage, PartialHTMLPage): @method - class iter_accounts(ListElement): - item_xpath = '//ul[@id="navSideProducts"]/li' + class get_account(ItemElement): + klass = Account - class item(ItemElement): - klass = Account + obj_type = Account.TYPE_CARD + obj_id = CleanText('//p[contains(text(), "Identifiant")]/a') + obj_label = obj_id + obj_currency = u'EUR' + obj_balance = MyDecimal('//p[@class="num"]/a') - obj_type = Account.TYPE_CARD - obj_id = CleanText('./a/p', replace=[('N° ', '')]) - obj_label = obj_id - obj_currency = u'EUR' - obj_balance = MyDecimal(u'//p[@class="num"]//strong') + # Every subscription a product token and a type ex: card = 240 + obj__product_token = Regexp(CleanText('//div[contains(@id, "product")]/@id'), r'productLine_(\d*)') + obj__product_type = Regexp(CleanText('(//div[@class="logo"])[1]//img/@src'), "/img/product_(\d*).png") - # Every subscription a product token and a type ex: card = 240 - obj__product_token = Regexp(CleanText('./@id'), r'navSideProduct_(\d*)') - obj__product_type = Regexp(CleanText('(//div[@class="logo"])[1]//img/@src'), "/img/product_(\d*).png") class TransactionsPage(LoggedPage, HTMLPage): @@ -73,6 +77,7 @@ class item(ItemElement): obj_label = CleanText('.//h3/strong') obj_raw = Field('label') obj_amount = MyDecimal('./td[@class="al-r"]/div/span[has-class("badge")]') + def obj_type(self): amount = Field('amount')(self) if amount < 0: diff --git a/modules/myfoncia/compat/__init__.py b/modules/myfoncia/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/myfoncia/compat/weboob_browser_filters_standard.py b/modules/myfoncia/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/myfoncia/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/myfoncia/pages.py b/modules/myfoncia/pages.py index b8c63f2b90..2fe5a9ff0c 100644 --- a/modules/myfoncia/pages.py +++ b/modules/myfoncia/pages.py @@ -20,7 +20,7 @@ from __future__ import unicode_literals from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import CleanDecimal, CleanText, Date, Env, Format +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Date, Env, Format from weboob.browser.filters.html import Attr, Link, XPathNotFound from weboob.browser.elements import ItemElement, ListElement, method from weboob.capabilities.base import NotAvailable diff --git a/modules/n26/browser.py b/modules/n26/browser.py index 74f437db64..4d99bd5cb2 100644 --- a/modules/n26/browser.py +++ b/modules/n26/browser.py @@ -24,7 +24,7 @@ from weboob.browser.browsers import DomainBrowser from weboob.capabilities.base import find_object, NotAvailable from weboob.capabilities.bank import Account, Transaction, AccountNotFound -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.exceptions import BrowserIncorrectPassword, BrowserUnavailable from weboob.browser.exceptions import ClientError diff --git a/modules/n26/compat/__init__.py b/modules/n26/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/n26/compat/weboob_browser_filters_standard.py b/modules/n26/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/n26/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/nalo/compat/__init__.py b/modules/nalo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/nalo/compat/weboob_browser_filters_standard.py b/modules/nalo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/nalo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/nalo/pages.py b/modules/nalo/pages.py index 77ee206a87..a7639d3111 100644 --- a/modules/nalo/pages.py +++ b/modules/nalo/pages.py @@ -24,7 +24,7 @@ from weboob.browser.pages import LoggedPage, JsonPage from weboob.browser.elements import method, DictElement, ItemElement from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import Eval +from .compat.weboob_browser_filters_standard import Eval from weboob.capabilities.bank import Account diff --git a/modules/nef/compat/__init__.py b/modules/nef/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/nef/compat/weboob_browser_filters_standard.py b/modules/nef/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/nef/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/nef/pages.py b/modules/nef/pages.py index 2e2b1d1880..4bda84aeef 100644 --- a/modules/nef/pages.py +++ b/modules/nef/pages.py @@ -22,7 +22,7 @@ import re from weboob.browser.elements import ListElement, DictElement, ItemElement, method, TableElement -from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, Field, Date +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Regexp, Field, Date from weboob.browser.pages import HTMLPage, PartialHTMLPage, CsvPage, LoggedPage from weboob.browser.filters.json import Dict from weboob.browser.filters.html import Attr, TableCell diff --git a/modules/netfinca/compat/__init__.py b/modules/netfinca/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/netfinca/compat/weboob_browser_filters_standard.py b/modules/netfinca/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/netfinca/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/netfinca/module.py b/modules/netfinca/module.py index 6987162d16..ef4382bbe9 100644 --- a/modules/netfinca/module.py +++ b/modules/netfinca/module.py @@ -20,6 +20,7 @@ from __future__ import unicode_literals +from weboob.capabilities.bank import CapBank from weboob.tools.backend import Module from .browser import NetfincaBrowser @@ -27,7 +28,7 @@ __all__ = ['NetfincaModule'] -class NetfincaModule(Module): +class NetfincaModule(Module, CapBank): NAME = 'netfinca' DESCRIPTION = 'netfinca website' MAINTAINER = 'Martin Sicot' diff --git a/modules/netfinca/pages.py b/modules/netfinca/pages.py index f40ce72cf6..1b9b39e9af 100644 --- a/modules/netfinca/pages.py +++ b/modules/netfinca/pages.py @@ -25,7 +25,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import method, ItemElement, TableElement -from weboob.browser.filters.standard import CleanText, CleanDecimal, Currency +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Currency from weboob.browser.filters.html import TableCell, Attr from weboob.capabilities.bank import Investment, Account from weboob.capabilities.base import NotAvailable diff --git a/modules/oney/browser.py b/modules/oney/browser.py index 15db5e6378..a7f5ee4f53 100644 --- a/modules/oney/browser.py +++ b/modules/oney/browser.py @@ -17,7 +17,9 @@ # You should have received a copy of the GNU Lesser General Public License # along with this weboob module. If not, see . -from datetime import date +from datetime import date, timedelta +from dateutil.relativedelta import relativedelta +from itertools import chain from weboob.exceptions import BrowserIncorrectPassword from weboob.browser import LoginBrowser, URL, need_login @@ -107,15 +109,29 @@ def get_accounts_list(self): return accounts - def _build_hist_form(self): + def _build_hist_form(self, last_months=False): form = {} d = date.today() - form['jourDebut'] = '1' - form['moisDebut'] = '1' - form['anneeDebut'] = '2016' - form['jourFin'] = str(d.day) - form['moisFin'] = str(d.month) - form['anneeFin'] = str(d.year) + + if not last_months: + # before the last two months + end = d.replace(day=1) + relativedelta(months=-1, days=-1) + form['jourDebut'] = '1' + form['moisDebut'] = '1' + form['anneeDebut'] = '2016' + form['jourFin'] = str(end.day) + form['moisFin'] = str(end.month) + form['anneeFin'] = str(end.year) + else: + # the last two months + start = d.replace(day=1) - timedelta(days=1) + form['jourDebut'] = '1' + form['moisDebut'] = str(start.month) + form['anneeDebut'] = str(start.year) + form['jourFin'] = str(d.day) + form['moisFin'] = str(d.month) + form['anneeFin'] = str(d.year) + form['typeOpe'] = 'deux' form['formatFichier'] = 'xls' # or pdf... great choice return form @@ -134,9 +150,17 @@ def iter_history(self, account): elif account._site == 'other': if self.last_hist.go().has_transactions(): - self.credit_hist.go(params=self._build_hist_form()) - d = date.today().replace(day=1) # TODO is it the right date? - for tr in self.page.iter_history(): + # transactions are missing from the xls from 2016 to today + # so two requests are needed + d = date.today() + page_before = self.credit_hist.open( + params=self._build_hist_form(last_months=True) + ) + page_today = self.credit_hist.go( + params=self._build_hist_form() + ) + + for tr in chain(page_before.iter_history(), page_today.iter_history()): if new_date(tr.date) < d: yield tr diff --git a/modules/oney/compat/weboob_browser_filters_standard.py b/modules/oney/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/oney/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/oney/pages.py b/modules/oney/pages.py index 4acfaca27e..094b50d904 100644 --- a/modules/oney/pages.py +++ b/modules/oney/pages.py @@ -31,7 +31,7 @@ from weboob.tools.date import parse_french_date from weboob.browser.pages import HTMLPage, LoggedPage, pagination, XLSPage, PartialHTMLPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import Env, CleanDecimal, CleanText, Field, Format, Currency +from .compat.weboob_browser_filters_standard import Env, CleanDecimal, CleanText, Field, Format, Currency from weboob.browser.filters.html import Attr from weboob.exceptions import BrowserIncorrectPassword diff --git a/modules/onlinenet/compat/__init__.py b/modules/onlinenet/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/onlinenet/compat/weboob_browser_filters_standard.py b/modules/onlinenet/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/onlinenet/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/onlinenet/pages.py b/modules/onlinenet/pages.py index b19d79998a..b483774d9e 100644 --- a/modules/onlinenet/pages.py +++ b/modules/onlinenet/pages.py @@ -21,7 +21,7 @@ import re from weboob.browser.pages import HTMLPage, LoggedPage -from weboob.browser.filters.standard import CleanText, CleanDecimal, Env, Format, Date +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Env, Format, Date from weboob.browser.filters.html import Attr, TableCell from weboob.browser.elements import ListElement, ItemElement, TableElement, method from weboob.capabilities.bill import DocumentTypes, Bill, Document, Subscription diff --git a/modules/opensubtitles/compat/__init__.py b/modules/opensubtitles/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/opensubtitles/compat/weboob_browser_filters_standard.py b/modules/opensubtitles/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/opensubtitles/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/opensubtitles/pages.py b/modules/opensubtitles/pages.py index 7ec3fecd80..045dd7d084 100644 --- a/modules/opensubtitles/pages.py +++ b/modules/opensubtitles/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import TableElement, ItemElement, method from weboob.browser.filters.html import Attr, Link, AbsoluteLink -from weboob.browser.filters.standard import Regexp, CleanText, CleanDecimal +from .compat.weboob_browser_filters_standard import Regexp, CleanText, CleanDecimal class SearchPage(HTMLPage): diff --git a/modules/orange/pages/bills.py b/modules/orange/pages/bills.py index d9cc37c47e..08eaef6a00 100644 --- a/modules/orange/pages/bills.py +++ b/modules/orange/pages/bills.py @@ -28,7 +28,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage from weboob.capabilities.bill import Subscription from weboob.browser.elements import DictElement, ListElement, ItemElement, method, TableElement -from weboob.browser.filters.standard import CleanDecimal, CleanText, Env, Field, Regexp, Date, Currency, BrowserURL, Format +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Env, Field, Regexp, Date, Currency, BrowserURL, Format from weboob.browser.filters.html import Link, TableCell from weboob.browser.filters.javascript import JSValue from weboob.browser.filters.json import Dict diff --git a/modules/orange/pages/compat/__init__.py b/modules/orange/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/orange/pages/compat/weboob_browser_filters_standard.py b/modules/orange/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/orange/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/orange/pages/login.py b/modules/orange/pages/login.py index 76aae259a2..bc3365d703 100644 --- a/modules/orange/pages/login.py +++ b/modules/orange/pages/login.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.tools.json import json -from weboob.browser.filters.standard import CleanText, Format +from .compat.weboob_browser_filters_standard import CleanText, Format class LoginPage(HTMLPage): diff --git a/modules/orange/pages/profile.py b/modules/orange/pages/profile.py index 8fe600f3cf..52a2a34439 100644 --- a/modules/orange/pages/profile.py +++ b/modules/orange/pages/profile.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.capabilities.profile import Profile -from weboob.browser.filters.standard import CleanText, Format +from .compat.weboob_browser_filters_standard import CleanText, Format class ProfilePage(LoggedPage, HTMLPage): diff --git a/modules/ovh/compat/__init__.py b/modules/ovh/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ovh/compat/weboob_browser_filters_standard.py b/modules/ovh/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ovh/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ovh/pages.py b/modules/ovh/pages.py index 376c9a3199..66e58a0a49 100644 --- a/modules/ovh/pages.py +++ b/modules/ovh/pages.py @@ -20,7 +20,7 @@ from weboob.capabilities.bill import DocumentTypes, Bill, Subscription from weboob.browser.pages import HTMLPage, LoggedPage, JsonPage -from weboob.browser.filters.standard import CleanDecimal, CleanText, Env, Format, Date +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Env, Format, Date from weboob.browser.filters.html import Attr from weboob.browser.filters.json import Dict from weboob.browser.elements import ListElement, ItemElement, method, DictElement diff --git a/modules/pagesjaunes/compat/__init__.py b/modules/pagesjaunes/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/pagesjaunes/compat/weboob_browser_filters_standard.py b/modules/pagesjaunes/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/pagesjaunes/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/pagesjaunes/pages.py b/modules/pagesjaunes/pages.py index db6b79833e..9868061276 100644 --- a/modules/pagesjaunes/pages.py +++ b/modules/pagesjaunes/pages.py @@ -24,7 +24,7 @@ from dateutil import rrule from weboob.browser.elements import method, ListElement, ItemElement -from weboob.browser.filters.standard import CleanText, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Regexp from weboob.browser.filters.html import AbsoluteLink, HasElement from weboob.browser.pages import HTMLPage from weboob.capabilities.base import NotLoaded, NotAvailable @@ -41,7 +41,10 @@ class item(ItemElement): obj_name = CleanText('.//a[has-class("denomination-links")]') obj_address = CleanText('.//a[has-class("adresse")]') - obj_phone = Regexp(CleanText('.//strong[@class="num"]', replace=[(' ', '')]), r'^0(\d{9})$', r'+33\1') + obj_phone = Regexp( + CleanText( + './/div[has-class("tel-zone")][span[contains(text(),"Tél")]]//strong[@class="num"]', + replace=[(' ', '')]), r'^0(\d{9})$', r'+33\1') obj_url = AbsoluteLink('.//a[has-class("denomination-links")]') obj_opening = HasElement('.//span[text()="Horaires"]', NotLoaded, NotAvailable) diff --git a/modules/pap/compat/__init__.py b/modules/pap/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/pap/compat/weboob_browser_filters_standard.py b/modules/pap/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/pap/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/pap/pages.py b/modules/pap/pages.py index 6eb6783712..792260046b 100644 --- a/modules/pap/pages.py +++ b/modules/pap/pages.py @@ -22,7 +22,7 @@ from weboob.tools.date import parse_french_date from weboob.browser.pages import HTMLPage, JsonPage, pagination from weboob.browser.elements import ItemElement, ListElement, DictElement, method -from weboob.browser.filters.standard import (CleanText, CleanDecimal, Regexp, +from .compat.weboob_browser_filters_standard import (CleanText, CleanDecimal, Regexp, Env, BrowserURL, Format, Currency) from weboob.browser.filters.html import Attr, Link, XPath, CleanHTML from weboob.browser.filters.json import Dict diff --git a/modules/paroles2chansons/compat/__init__.py b/modules/paroles2chansons/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/paroles2chansons/compat/weboob_browser_filters_standard.py b/modules/paroles2chansons/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/paroles2chansons/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/paroles2chansons/pages.py b/modules/paroles2chansons/pages.py index 7f5339dd07..6023cbdd54 100644 --- a/modules/paroles2chansons/pages.py +++ b/modules/paroles2chansons/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText +from .compat.weboob_browser_filters_standard import Regexp, CleanText from weboob.browser.filters.html import CleanHTML diff --git a/modules/parolesmania/compat/__init__.py b/modules/parolesmania/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/parolesmania/compat/weboob_browser_filters_standard.py b/modules/parolesmania/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/parolesmania/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/parolesmania/pages.py b/modules/parolesmania/pages.py index 15afecfe62..0c896d1341 100644 --- a/modules/parolesmania/pages.py +++ b/modules/parolesmania/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText +from .compat.weboob_browser_filters_standard import Regexp, CleanText from weboob.browser.filters.html import CleanHTML diff --git a/modules/parolesmusique/compat/__init__.py b/modules/parolesmusique/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/parolesmusique/compat/weboob_browser_filters_standard.py b/modules/parolesmusique/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/parolesmusique/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/parolesmusique/pages.py b/modules/parolesmusique/pages.py index b027a120bd..c9d057d295 100644 --- a/modules/parolesmusique/pages.py +++ b/modules/parolesmusique/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText, Format +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Format from weboob.browser.filters.html import CleanHTML import random diff --git a/modules/parolesnet/compat/__init__.py b/modules/parolesnet/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/parolesnet/compat/weboob_browser_filters_standard.py b/modules/parolesnet/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/parolesnet/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/parolesnet/pages.py b/modules/parolesnet/pages.py index df4423af3e..d9f0e9bc09 100644 --- a/modules/parolesnet/pages.py +++ b/modules/parolesnet/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import Regexp, CleanText +from .compat.weboob_browser_filters_standard import Regexp, CleanText from weboob.browser.filters.html import CleanHTML diff --git a/modules/pastealacon/browser.py b/modules/pastealacon/browser.py index 65af6fb265..bab99587f7 100644 --- a/modules/pastealacon/browser.py +++ b/modules/pastealacon/browser.py @@ -20,7 +20,7 @@ import re from weboob.capabilities.paste import BasePaste, PasteNotFound -from weboob.browser.filters.standard import BrowserURL, CleanText, DateTime, Env, Field, RawText, Regexp +from .compat.weboob_browser_filters_standard import BrowserURL, CleanText, DateTime, Env, Field, RawText, Regexp from weboob.browser.pages import HTMLPage from weboob.browser.browsers import PagesBrowser from weboob.browser.url import URL diff --git a/modules/pastealacon/compat/__init__.py b/modules/pastealacon/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/pastealacon/compat/weboob_browser_filters_standard.py b/modules/pastealacon/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/pastealacon/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/pastebin/browser.py b/modules/pastebin/browser.py index 42214cdccd..81d0c87bb7 100644 --- a/modules/pastebin/browser.py +++ b/modules/pastebin/browser.py @@ -20,10 +20,10 @@ import re -from weboob.browser import URL, LoginBrowser, need_login +from weboob.browser.browsers import URL, LoginBrowser, need_login from weboob.browser.elements import ItemElement, method from weboob.browser.filters.html import Attr -from weboob.browser.filters.standard import Base, BrowserURL, CleanText, DateTime, Env, Field, Filter, FilterError, RawText +from .compat.weboob_browser_filters_standard import Base, BrowserURL, CleanText, DateTime, Env, Field, Filter, FilterError, RawText from weboob.browser.pages import HTMLPage, RawPage from weboob.capabilities.paste import BasePaste, PasteNotFound from weboob.exceptions import BrowserHTTPNotFound, BrowserIncorrectPassword, BrowserUnavailable diff --git a/modules/pastebin/compat/__init__.py b/modules/pastebin/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/pastebin/compat/weboob_browser_filters_standard.py b/modules/pastebin/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/pastebin/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/paypal/compat/__init__.py b/modules/paypal/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/paypal/compat/weboob_browser_filters_standard.py b/modules/paypal/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/paypal/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/paypal/pages.py b/modules/paypal/pages.py index 00bb95426c..f62e0031f5 100644 --- a/modules/paypal/pages.py +++ b/modules/paypal/pages.py @@ -27,7 +27,7 @@ from weboob.exceptions import BrowserUnavailable, ActionNeeded from weboob.browser.exceptions import ServerError from weboob.browser.pages import HTMLPage, JsonPage, LoggedPage -from weboob.browser.filters.standard import CleanText, CleanDecimal +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.date import parse_french_date from weboob.tools.js import Javascript diff --git a/modules/phpbb/pages/compat/__init__.py b/modules/phpbb/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/phpbb/pages/compat/weboob_browser_filters_standard.py b/modules/phpbb/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/phpbb/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/phpbb/pages/forum.py b/modules/phpbb/pages/forum.py index 17a0833013..d0aafdf50a 100644 --- a/modules/phpbb/pages/forum.py +++ b/modules/phpbb/pages/forum.py @@ -20,7 +20,7 @@ from time import sleep -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.tools.compat import urlsplit, parse_qs from .index import PhpBBPage diff --git a/modules/piratebay/pages/compat/__init__.py b/modules/piratebay/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/piratebay/pages/compat/weboob_browser_filters_standard.py b/modules/piratebay/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/piratebay/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/piratebay/pages/torrents.py b/modules/piratebay/pages/torrents.py index e01000c0c9..aee74ed6ed 100644 --- a/modules/piratebay/pages/torrents.py +++ b/modules/piratebay/pages/torrents.py @@ -22,7 +22,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.capabilities.torrent import Torrent from weboob.capabilities.base import NotAvailable -from weboob.browser.filters.standard import RawText, CleanText, Regexp, Date, Type +from .compat.weboob_browser_filters_standard import RawText, CleanText, Regexp, Date, Type class TorrentsPage(HTMLPage): diff --git a/modules/podnapisi/compat/__init__.py b/modules/podnapisi/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/podnapisi/compat/weboob_browser_filters_standard.py b/modules/podnapisi/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/podnapisi/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/podnapisi/pages.py b/modules/podnapisi/pages.py index 7313c07143..fb94557a2c 100644 --- a/modules/podnapisi/pages.py +++ b/modules/podnapisi/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import TableElement, ItemElement, method from weboob.browser.pages import HTMLPage, pagination from weboob.browser.filters.html import TableCell, AbsoluteLink, Attr -from weboob.browser.filters.standard import CleanText, Field, Type, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Field, Type, Regexp from weboob.capabilities.subtitle import Subtitle from weboob.tools.compat import urljoin diff --git a/modules/poivy/compat/__init__.py b/modules/poivy/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/poivy/compat/weboob_browser_filters_standard.py b/modules/poivy/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/poivy/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/poivy/pages.py b/modules/poivy/pages.py index d7ae47d70d..d95190020f 100644 --- a/modules/poivy/pages.py +++ b/modules/poivy/pages.py @@ -20,7 +20,7 @@ from weboob.exceptions import BrowserBanned from weboob.browser.pages import HTMLPage, LoggedPage, pagination from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, CleanDecimal, Field, DateTime, Format +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Field, DateTime, Format from weboob.browser.filters.html import Attr, Link from weboob.capabilities.bill import Subscription, Detail diff --git a/modules/popolemploi/compat/__init__.py b/modules/popolemploi/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/popolemploi/compat/weboob_browser_filters_standard.py b/modules/popolemploi/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/popolemploi/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/popolemploi/pages.py b/modules/popolemploi/pages.py index db8dedb913..4102088fdf 100644 --- a/modules/popolemploi/pages.py +++ b/modules/popolemploi/pages.py @@ -20,7 +20,7 @@ from weboob.capabilities.job import BaseJobAdvert from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Regexp, CleanText, Env, BrowserURL, Filter, Join +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Env, BrowserURL, Filter, Join from weboob.browser.filters.html import XPath diff --git a/modules/pornhub/compat/__init__.py b/modules/pornhub/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/pornhub/compat/weboob_browser_filters_standard.py b/modules/pornhub/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/pornhub/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/pornhub/pages.py b/modules/pornhub/pages.py index b13adaf2fd..e0b8624cea 100644 --- a/modules/pornhub/pages.py +++ b/modules/pornhub/pages.py @@ -20,7 +20,7 @@ from weboob.browser.elements import ListElement, ItemElement, method from weboob.browser.filters.html import Link, CSS, Attr -from weboob.browser.filters.standard import CleanText, Duration, Regexp, Env +from .compat.weboob_browser_filters_standard import CleanText, Duration, Regexp, Env from weboob.browser.pages import HTMLPage, pagination from weboob.capabilities.base import NotAvailable from weboob.capabilities.image import Thumbnail diff --git a/modules/prixcarburants/compat/__init__.py b/modules/prixcarburants/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/prixcarburants/compat/weboob_browser_filters_standard.py b/modules/prixcarburants/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/prixcarburants/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/prixcarburants/pages.py b/modules/prixcarburants/pages.py index cdc9f195ef..47958201c4 100644 --- a/modules/prixcarburants/pages.py +++ b/modules/prixcarburants/pages.py @@ -18,7 +18,7 @@ # along with this weboob module. If not, see . from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import CleanText, Env, Field, CleanDecimal, Date, Format +from .compat.weboob_browser_filters_standard import CleanText, Env, Field, CleanDecimal, Date, Format from weboob.browser.elements import ItemElement, ListElement, method from weboob.capabilities.pricecomparison import Product, Shop, Price diff --git a/modules/radiofrance/compat/__init__.py b/modules/radiofrance/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/radiofrance/compat/weboob_browser_filters_standard.py b/modules/radiofrance/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/radiofrance/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/radiofrance/pages.py b/modules/radiofrance/pages.py index 80b89611e6..74766d825c 100644 --- a/modules/radiofrance/pages.py +++ b/modules/radiofrance/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage, JsonPage, XMLPage from weboob.browser.filters.json import Dict from weboob.browser.filters.html import XPath -from weboob.browser.filters.standard import Format, CleanText, Join, Env, Regexp, Duration, Time +from .compat.weboob_browser_filters_standard import Format, CleanText, Join, Env, Regexp, Duration, Time from weboob.capabilities.audio import BaseAudio from weboob.tools.capabilities.audio.audio import BaseAudioIdFilter from weboob.capabilities.image import Thumbnail diff --git a/modules/ratp/compat/__init__.py b/modules/ratp/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ratp/compat/weboob_browser_filters_standard.py b/modules/ratp/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ratp/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ratp/pages.py b/modules/ratp/pages.py index e2c2e25164..bcd325a25f 100644 --- a/modules/ratp/pages.py +++ b/modules/ratp/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import method, ItemElement, ListElement from weboob.browser.filters.html import Attr -from weboob.browser.filters.standard import CleanText, Eval +from .compat.weboob_browser_filters_standard import CleanText, Eval from weboob.browser.pages import HTMLPage from weboob.capabilities.gauge import Gauge, GaugeMeasure diff --git a/modules/razibus/compat/__init__.py b/modules/razibus/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/razibus/compat/weboob_browser_filters_standard.py b/modules/razibus/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/razibus/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/razibus/pages.py b/modules/razibus/pages.py index ea62cc7514..73fb2dde59 100644 --- a/modules/razibus/pages.py +++ b/modules/razibus/pages.py @@ -24,7 +24,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.filters.html import CleanHTML, Link -from weboob.browser.filters.standard import Regexp, CleanText, DateTime, CombineDate, Filter, Env +from .compat.weboob_browser_filters_standard import Regexp, CleanText, DateTime, CombineDate, Filter, Env class EndTime(Filter): diff --git a/modules/reddit/compat/__init__.py b/modules/reddit/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/reddit/compat/weboob_browser_filters_standard.py b/modules/reddit/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/reddit/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/reddit/pages.py b/modules/reddit/pages.py index ae11da5952..49092d049e 100644 --- a/modules/reddit/pages.py +++ b/modules/reddit/pages.py @@ -22,7 +22,7 @@ from collections import OrderedDict from weboob.browser.elements import method, ListElement, ItemElement, SkipItem -from weboob.browser.filters.standard import CleanText, Regexp, Field, DateTime +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Field, DateTime from weboob.browser.filters.html import AbsoluteLink, Link, Attr, CleanHTML from weboob.browser.pages import HTMLPage, RawPage, pagination from weboob.capabilities.image import BaseImage, Thumbnail diff --git a/modules/redmine/pages/compat/__init__.py b/modules/redmine/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/redmine/pages/compat/weboob_browser_filters_standard.py b/modules/redmine/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/redmine/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/redmine/pages/issues.py b/modules/redmine/pages/issues.py index b9394d2ee0..f1dd222a9a 100644 --- a/modules/redmine/pages/issues.py +++ b/modules/redmine/pages/issues.py @@ -25,7 +25,7 @@ from weboob.tools.date import parse_french_date from weboob.tools.json import json from weboob.tools.misc import to_unicode -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from .index import BaseHTMLPage diff --git a/modules/regionsjob/compat/__init__.py b/modules/regionsjob/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/regionsjob/compat/weboob_browser_filters_standard.py b/modules/regionsjob/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/regionsjob/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/regionsjob/pages.py b/modules/regionsjob/pages.py index cc39e13370..ca20f176f5 100644 --- a/modules/regionsjob/pages.py +++ b/modules/regionsjob/pages.py @@ -19,7 +19,7 @@ from weboob.browser.pages import HTMLPage, pagination, JsonPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Env, Date, BrowserURL, Join +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env, Date, BrowserURL, Join from weboob.browser.filters.html import CleanHTML, Link from weboob.browser.filters.json import Dict from weboob.capabilities.job import BaseJobAdvert diff --git a/modules/residentadvisor/compat/__init__.py b/modules/residentadvisor/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/residentadvisor/compat/weboob_browser_filters_standard.py b/modules/residentadvisor/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/residentadvisor/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/residentadvisor/pages.py b/modules/residentadvisor/pages.py index 5f957707ff..09f4aa885f 100644 --- a/modules/residentadvisor/pages.py +++ b/modules/residentadvisor/pages.py @@ -21,7 +21,7 @@ from weboob.capabilities.calendar import CATEGORIES, STATUS, TICKET from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.filters.html import Attr, CleanHTML, Link -from weboob.browser.filters.standard import CleanDecimal, CleanText, Date, CombineDate, DateTime, Regexp, Time, Type +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Date, CombineDate, DateTime, Regexp, Time, Type from weboob.browser.pages import HTMLPage from weboob.capabilities.calendar import BaseCalendarEvent diff --git a/modules/rmll/compat/__init__.py b/modules/rmll/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/rmll/compat/weboob_browser_filters_standard.py b/modules/rmll/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/rmll/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/rmll/pages.py b/modules/rmll/pages.py index 3719df03d4..c47a7b8bdb 100644 --- a/modules/rmll/pages.py +++ b/modules/rmll/pages.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.filters.html import CleanHTML, Link, XPath from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanText, DateTime, Duration, Filter, Format, Regexp +from .compat.weboob_browser_filters_standard import CleanText, DateTime, Duration, Filter, Format, Regexp from weboob.browser.pages import HTMLPage, JsonPage from weboob.capabilities import NotLoaded from weboob.capabilities.collection import Collection diff --git a/modules/s2e/compat/weboob_browser_filters_standard.py b/modules/s2e/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/s2e/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/s2e/pages.py b/modules/s2e/pages.py index 50d71f4554..5825debd7a 100644 --- a/modules/s2e/pages.py +++ b/modules/s2e/pages.py @@ -26,7 +26,7 @@ from weboob.browser.pages import HTMLPage, XMLPage, RawPage, LoggedPage, pagination, FormNotFound, PartialHTMLPage from weboob.browser.elements import ItemElement, TableElement, SkipItem, method -from weboob.browser.filters.standard import CleanText, Date, Regexp, Eval, CleanDecimal, Env, Field +from .compat.weboob_browser_filters_standard import CleanText, Date, Regexp, Eval, CleanDecimal, Env, Field from weboob.browser.filters.html import Attr, TableCell from weboob.capabilities.bank import Account, Investment, Pocket, Transaction from weboob.capabilities.base import NotAvailable diff --git a/modules/sachsen/compat/__init__.py b/modules/sachsen/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/sachsen/compat/weboob_browser_filters_standard.py b/modules/sachsen/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/sachsen/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/sachsen/pages.py b/modules/sachsen/pages.py index 50c96013bb..d0fe998fe0 100644 --- a/modules/sachsen/pages.py +++ b/modules/sachsen/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import Env, CleanText, Regexp, Field, DateTime, Map +from .compat.weboob_browser_filters_standard import Env, CleanText, Regexp, Field, DateTime, Map from weboob.browser.filters.html import Attr from weboob.capabilities.gauge import Gauge, GaugeMeasure, GaugeSensor from weboob.capabilities.base import NotAvailable, NotLoaded diff --git a/modules/seloger/compat/__init__.py b/modules/seloger/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/seloger/compat/weboob_browser_filters_standard.py b/modules/seloger/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/seloger/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/seloger/pages.py b/modules/seloger/pages.py index 0941f87f67..4069cdc3e4 100644 --- a/modules/seloger/pages.py +++ b/modules/seloger/pages.py @@ -22,7 +22,7 @@ from weboob.browser.elements import ItemElement, ListElement, DictElement, method from weboob.browser.filters.json import Dict from weboob.browser.filters.html import XPath -from weboob.browser.filters.standard import (CleanText, CleanDecimal, Currency, +from .compat.weboob_browser_filters_standard import (CleanText, CleanDecimal, Currency, DateTime, Env, Format, Regexp) from weboob.capabilities.base import NotAvailable, NotLoaded from weboob.capabilities.housing import (Housing, HousingPhoto, City, diff --git a/modules/senscritique/compat/__init__.py b/modules/senscritique/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/senscritique/compat/weboob_browser_filters_standard.py b/modules/senscritique/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/senscritique/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/senscritique/pages.py b/modules/senscritique/pages.py index c729cbba71..914d3b8569 100644 --- a/modules/senscritique/pages.py +++ b/modules/senscritique/pages.py @@ -24,7 +24,7 @@ from weboob.capabilities.base import empty from weboob.browser.pages import HTMLPage, JsonPage from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import Filter, CleanText, Regexp, Join, Format, BrowserURL, Env +from .compat.weboob_browser_filters_standard import Filter, CleanText, Regexp, Join, Format, BrowserURL, Env from weboob.browser.filters.html import Link diff --git a/modules/societegenerale/browser.py b/modules/societegenerale/browser.py index 67ffaf2afb..e7bf32a0da 100644 --- a/modules/societegenerale/browser.py +++ b/modules/societegenerale/browser.py @@ -25,7 +25,7 @@ from weboob.browser import LoginBrowser, URL, need_login, StatesMixin from weboob.exceptions import BrowserIncorrectPassword, ActionNeeded, BrowserUnavailable -from weboob.capabilities.bank import Account, TransferBankError, AddRecipientStep +from weboob.capabilities.bank import Account, TransferBankError, AddRecipientStep, TransactionType from weboob.capabilities.base import find_object, NotAvailable from weboob.browser.exceptions import BrowserHTTPNotFound, ClientError from weboob.capabilities.profile import ProfileMissing @@ -108,7 +108,9 @@ class SocieteGenerale(LoginBrowser, StatesMixin): r'/com/icd-web/forms/kyc-index.html', ActionNeededPage) unavailable_service_page = URL(r'/com/service-indisponible.html', - r'.*/Technical-pages/503-error-page/unavailable.html', UnavailableServicePage) + r'.*/Technical-pages/503-error-page/unavailable.html' + r'.*/Technical-pages/service-indisponible/service-indisponible.html', + UnavailableServicePage) error = URL(r'https://static.societegenerale.fr/pri/erreur.html', ErrorPage) login = URL(r'/sec/vk', LoginPage) main_page = URL(r'https://particuliers.societegenerale.fr', MainPage) @@ -251,6 +253,9 @@ def iter_history(self, account): for card_tr in summary_card_tr._card_transactions: card_tr.date = summary_card_tr.date + # We use the Raw pattern to set the rdate automatically, but that make + # the transaction type to "CARD", so we have to correct it in the browser. + card_tr.type = TransactionType.DEFERRED_CARD yield card_tr return @@ -284,6 +289,9 @@ def iter_coming(self, account): if transaction._card_coming: for card_coming in transaction._card_coming: card_coming.date = transaction.date + # We use the Raw pattern to set the rdate automatically, but that make + # the transaction type to "CARD", so we have to correct it in the browser. + card_coming.type = TransactionType.DEFERRED_CARD yield card_coming return diff --git a/modules/societegenerale/pages/accounts_list.py b/modules/societegenerale/pages/accounts_list.py index 0028a6fd5b..fa351a6d9b 100644 --- a/modules/societegenerale/pages/accounts_list.py +++ b/modules/societegenerale/pages/accounts_list.py @@ -31,7 +31,7 @@ from weboob.tools.capabilities.bank.investments import is_isin_valid, create_french_liquidity from weboob.browser.elements import DictElement, ItemElement, TableElement, method, ListElement from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Regexp, Currency, Eval, Field, Format, Date, Env, ) from weboob.browser.filters.html import Link, TableCell @@ -149,9 +149,11 @@ def condition(self): 'PEA_PME_ESPECES': Account.TYPE_PEA, 'COMPTE_TITRE_PEA': Account.TYPE_PEA, 'COMPTE_TITRE_PEA_PME': Account.TYPE_PEA, + 'VIE_LMP': Account.TYPE_LIFE_INSURANCE, 'PROJECTIS': Account.TYPE_LIFE_INSURANCE, 'VIE_FEDER': Account.TYPE_LIFE_INSURANCE, 'PALISSANDRE': Account.TYPE_LIFE_INSURANCE, + 'PROJECTIS_PROFESS': Account.TYPE_LIFE_INSURANCE, 'SOGECAPI_PATRIMOINE': Account.TYPE_LIFE_INSURANCE, 'EBENE_CAPITALISATION': Account.TYPE_LIFE_INSURANCE, 'ASSURANCE_VIE_GENERALE': Account.TYPE_LIFE_INSURANCE, @@ -428,8 +430,8 @@ class tr_item(TransactionItemElement): def condition(self): return Dict('statutOperation')(self) == 'COMPTABILISE' - obj_raw = Dict('libOpe') - obj_type = Transaction.TYPE_DEFERRED_CARD + obj_raw = Transaction.Raw(Dict('libOpe')) + obj_bdate = Eval(lambda t: datetime.date.fromtimestamp(int(t) / 1000), Dict('dateOpe')) @pagination @method @@ -472,7 +474,7 @@ class tr_item(ItemElement): klass = Transaction obj_amount = CleanDecimal(Dict('montant/value')) - obj_date = obj_vdate = Date(Dict('dateEcheance')) + obj_date = obj_vdate = obj_bdate = Date(Dict('dateEcheance')) obj_raw = Transaction.Raw(Dict('libelleOrigine')) @@ -544,15 +546,28 @@ def get_history_url(self): if history_link: return history_link.group(1) - def iter_history(self): - is_no_transaction_msg = any(( - self.doc.xpath(u'//div[contains(text(), "Aucune opération trouvée sur la période de restitution possible")]'), - self.doc.xpath(u'//div[contains(text(), "Aucune opération n\'a été réalisée depuis le dernier relevé")]'), - )) - assert is_no_transaction_msg, 'There are transactions, retrieve them !' + @method + class iter_history(TableElement): + head_xpath = '//table[not(@id)]//td/div[contains(@class, "tableauHead")]' + item_xpath = '//table[@id]//tr' + + def condition(self): + no_transaction_msg = any(( + self.xpath('//div[contains(text(), "Aucune opération trouvée sur la période de restitution possible")]'), + self.xpath('//div[contains(text(), "Aucune opération n\'a été réalisée depuis le dernier relevé")]'), + )) + return not no_transaction_msg + + col_label = 'Libellé' + col_amount = 'Montant' + col_date = 'Date' + + class item(ItemElement): + klass = Transaction - # waiting for account with history - return [] + obj_label = CleanText(TableCell('label')) + obj_amount = CleanDecimal(TableCell('amount')) + obj_date = Date(CleanText(TableCell('date')), dayfirst=True) class LifeInsurance(LoggedPage, HTMLPage): diff --git a/modules/societegenerale/pages/base.py b/modules/societegenerale/pages/base.py index 2fcaa3aef1..14f422cc32 100644 --- a/modules/societegenerale/pages/base.py +++ b/modules/societegenerale/pages/base.py @@ -23,7 +23,7 @@ from weboob.capabilities.base import NotAvailable from weboob.browser.pages import HTMLPage from weboob.tools.capabilities.bank.transactions import FrenchTransaction -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText class BasePage(HTMLPage): diff --git a/modules/societegenerale/pages/compat/__init__.py b/modules/societegenerale/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/societegenerale/pages/compat/weboob_browser_filters_standard.py b/modules/societegenerale/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/societegenerale/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/societegenerale/pages/login.py b/modules/societegenerale/pages/login.py index b137d295a5..526cd3a1c6 100644 --- a/modules/societegenerale/pages/login.py +++ b/modules/societegenerale/pages/login.py @@ -26,7 +26,7 @@ from weboob.exceptions import BrowserUnavailable, BrowserPasswordExpired, ActionNeeded from weboob.browser.pages import HTMLPage, JsonPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.browser.filters.json import Dict from .base import BasePage diff --git a/modules/societegenerale/pages/subscription.py b/modules/societegenerale/pages/subscription.py index c8844dd3f7..87d299e503 100644 --- a/modules/societegenerale/pages/subscription.py +++ b/modules/societegenerale/pages/subscription.py @@ -24,7 +24,7 @@ from weboob.capabilities.bill import Document, Subscription from weboob.browser.elements import TableElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Regexp, Env, Date, Format, Field +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env, Date, Format, Field from weboob.browser.filters.html import Link, TableCell, Attr from weboob.browser.pages import LoggedPage diff --git a/modules/societegenerale/pages/transfer.py b/modules/societegenerale/pages/transfer.py index c724c5a399..98fd59b745 100644 --- a/modules/societegenerale/pages/transfer.py +++ b/modules/societegenerale/pages/transfer.py @@ -27,7 +27,7 @@ ) from weboob.tools.capabilities.bank.iban import is_iban_valid from weboob.capabilities.base import NotAvailable -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Env, Date, Field, Format, ) from weboob.browser.filters.html import Link diff --git a/modules/societegenerale/sgpe/compat/__init__.py b/modules/societegenerale/sgpe/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/societegenerale/sgpe/compat/weboob_browser_filters_standard.py b/modules/societegenerale/sgpe/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/societegenerale/sgpe/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/societegenerale/sgpe/json_pages.py b/modules/societegenerale/sgpe/json_pages.py index ce9d67f7df..0f273d6157 100644 --- a/modules/societegenerale/sgpe/json_pages.py +++ b/modules/societegenerale/sgpe/json_pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import LoggedPage, JsonPage, pagination from weboob.browser.elements import ItemElement, method, DictElement -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanDecimal, CleanText, Date, Format, BrowserURL, Env, Field, ) diff --git a/modules/societegenerale/sgpe/pages.py b/modules/societegenerale/sgpe/pages.py index df869fbc00..86ef8d841d 100644 --- a/modules/societegenerale/sgpe/pages.py +++ b/modules/societegenerale/sgpe/pages.py @@ -25,7 +25,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, CleanDecimal, Date, Env, Regexp, Field, Format, ) diff --git a/modules/societegenerale/sgpe/transfer_pages.py b/modules/societegenerale/sgpe/transfer_pages.py index ac4052a2c1..321edfed68 100644 --- a/modules/societegenerale/sgpe/transfer_pages.py +++ b/modules/societegenerale/sgpe/transfer_pages.py @@ -25,10 +25,10 @@ from weboob.browser.pages import LoggedPage, HTMLPage, JsonPage from weboob.browser.elements import method, DictElement, ItemElement -from weboob.browser.filters.standard import CleanText, CleanDecimal +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal from weboob.browser.filters.html import Attr from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import Date, Eval +from .compat.weboob_browser_filters_standard import Date, Eval from weboob.capabilities.bank import Recipient, Transfer from .pages import LoginPage diff --git a/modules/sogecartenet/compat/__init__.py b/modules/sogecartenet/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/sogecartenet/compat/weboob_browser_filters_standard.py b/modules/sogecartenet/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/sogecartenet/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/sogecartenet/pages.py b/modules/sogecartenet/pages.py index 04f1bcd6db..ec07000444 100644 --- a/modules/sogecartenet/pages.py +++ b/modules/sogecartenet/pages.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage, CsvPage, pagination from weboob.exceptions import BrowserIncorrectPassword, BrowserPasswordExpired, NoAccountsException from weboob.browser.elements import DictElement, ItemElement, method, TableElement -from weboob.browser.filters.standard import CleanText, CleanDecimal, Date, Env +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Date, Env from weboob.browser.filters.html import TableCell from weboob.browser.filters.json import Dict from weboob.capabilities.bank import Account diff --git a/modules/spirica/browser.py b/modules/spirica/browser.py index 9df2fbee7a..0fd87443c3 100644 --- a/modules/spirica/browser.py +++ b/modules/spirica/browser.py @@ -21,12 +21,13 @@ from weboob.browser import LoginBrowser, URL, need_login from weboob.exceptions import BrowserIncorrectPassword +from weboob.browser.exceptions import ClientError from .pages import LoginPage, AccountsPage, DetailsPage, MaintenancePage class SpiricaBrowser(LoginBrowser): - TIMEOUT = 60 + TIMEOUT = 180 login = URL('/securite/login.xhtml', LoginPage) accounts = URL('/sylvea/client/synthese.xhtml', AccountsPage) @@ -38,6 +39,7 @@ def __init__(self, website, *args, **kwargs): self.BASEURL = website self.cache = {} self.cache['invs'] = {} + self.transaction_page = None def do_login(self): self.login.go().login(self.username, self.password) @@ -65,25 +67,72 @@ def iter_investment(self, account): self.cache['invs'][account.id] = invs return self.cache['invs'][account.id] + def check_if_logged_in(self, url): + if self.login.is_here(): + self.logger.warning('We were logged out during iter_history, proceed to re-login.') + self.do_login() + self.location(url) + self.page.go_historytab() + # Store new transaction_page after login: + self.transaction_page = self.page + + @need_login + def get_transactions_with_investments(self, max_count, url): + transactions = [] + for index, transaction in enumerate(self.page.iter_history()): + self.check_if_logged_in(url) + if index < max_count: + try: + self.transaction_page.go_investments_form(transaction._index) + except ClientError as e: + self.logger.warning(e) + # Check if we are logged out + if self.login.is_here(): + self.check_if_logged_in(url) + if self.details.is_here(): + transaction.investments = [] + for inv in self.page.iter_transactions_investments(): + # Only keep investments that have at least a label and a valuation: + if inv.label and inv.valuation: + transaction.investments.append(inv) + transactions.append(transaction) + return transactions + @need_login def iter_history(self, account): self.location(account.url) self.page.go_historytab() - transaction_page = self.page + self.transaction_page = self.page # Determining the number of transaction pages: total_pages = int(self.page.count_transactions()) // 100 - # Scraping transactions for each page: - for page_number in range(total_pages + 1): - self.page.go_historyall(page_number) + # Scraping transactions with their investments for the 20 first transactions. + # Sometimes go_historyall fails so we go back to the accounts page and retry. + if self.transaction_page.go_historyall(page_number=0): + for tr in self.get_transactions_with_investments(20, account.url): + yield tr + else: + self.logger.warning('The first go_historyall() failed, go back to account details and retry.') + self.location(account.url) + self.page.go_historytab() + self.transaction_page = self.page + if self.transaction_page.go_historyall(page_number=0): + for tr in self.get_transactions_with_investments(20, account.url): + yield tr + + # Scraping other transaction pages without their investments: + for page_number in range(1, total_pages + 1): + self.check_if_logged_in(account.url) + if not self.transaction_page.go_historyall(page_number): + self.logger.warning('The first go_historyall() failed, go back to account details and retry.') + self.location(account.url) + self.page.go_historytab() + self.transaction_page = self.page + if not self.transaction_page.go_historyall(page_number): + self.logger.warning('The go_historyall() failed twice, these transactions will be skipped.') + continue for transaction in self.page.iter_history(): - transaction_page.go_investments_form(transaction._index) - transaction.investments = [] - for inv in self.page.iter_transactions_investments(): - # Only keep investments that have at least a label and a valuation: - if inv.label and inv.valuation: - transaction.investments.append(inv) yield transaction def fill_from_list(self, invs, objects_list): diff --git a/modules/spirica/compat/__init__.py b/modules/spirica/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/spirica/compat/weboob_browser_filters_standard.py b/modules/spirica/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/spirica/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/spirica/pages.py b/modules/spirica/pages.py index 016665b88e..9f24afa36d 100644 --- a/modules/spirica/pages.py +++ b/modules/spirica/pages.py @@ -23,7 +23,7 @@ from weboob.browser.pages import HTMLPage, LoggedPage from weboob.browser.elements import ItemElement, ListElement, TableElement, method -from weboob.browser.filters.standard import CleanText, Date, Regexp, CleanDecimal, \ +from .compat.weboob_browser_filters_standard import CleanText, Date, Regexp, CleanDecimal, \ Field, Async, AsyncLoad, Eval, Currency from weboob.browser.filters.html import Attr, Link, TableCell from weboob.capabilities.bank import Account, Investment, Transaction @@ -227,8 +227,11 @@ def go_historytab(self): def go_historyall(self, page_number): form = self.get_form(xpath='//form[contains(@id, "ongletHistoOperations:ongletHistoriqueOperations")]') - # The form value varies (for example j_idt913 or j_idt62081) so we need to scrape it dynamically: - form_value = Attr('//div[@id="ongletHistoOperations:ongletHistoriqueOperations:newoperations"]/div[1]', 'id')(self.doc) + # The form value varies (for example j_idt913 or j_idt62081) so we need to scrape it dynamically. + # However, sometimes the form does not contain the 'id' attribute, in which case we must reload the page. + form_value = Attr('//div[@id="ongletHistoOperations:ongletHistoriqueOperations:newoperations"]/div[1]', 'id', default=None)(self.doc) + if not form_value: + return False form['javax.faces.partial.ajax'] = 'true' form['javax.faces.partial.execute'] = form_value form['javax.faces.partial.render'] = form_value @@ -239,6 +242,7 @@ def go_historyall(self, page_number): form[form_value + '_rows'] = '100' form[form_value + '_first'] = page_number * 100 form.submit() + return True def go_investments_form(self, index): form = self.get_form(xpath='//form[contains(@id, "ongletHistoOperations:ongletHistoriqueOperations")]') diff --git a/modules/sprunge/browser.py b/modules/sprunge/browser.py index 35a56697d9..3761648fe0 100644 --- a/modules/sprunge/browser.py +++ b/modules/sprunge/browser.py @@ -19,7 +19,7 @@ from weboob.browser.browsers import PagesBrowser from weboob.browser.elements import ItemElement, method -from weboob.browser.filters.standard import BrowserURL, Env, Field +from .compat.weboob_browser_filters_standard import BrowserURL, Env, Field from weboob.browser.pages import HTMLPage from weboob.browser.url import URL from weboob.capabilities.base import NotAvailable diff --git a/modules/sprunge/compat/__init__.py b/modules/sprunge/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/sprunge/compat/weboob_browser_filters_standard.py b/modules/sprunge/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/sprunge/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/sueurdemetal/compat/__init__.py b/modules/sueurdemetal/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/sueurdemetal/compat/weboob_browser_filters_standard.py b/modules/sueurdemetal/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/sueurdemetal/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/sueurdemetal/pages.py b/modules/sueurdemetal/pages.py index 2bc892ac10..93550b9928 100644 --- a/modules/sueurdemetal/pages.py +++ b/modules/sueurdemetal/pages.py @@ -25,7 +25,7 @@ from weboob.browser.pages import JsonPage from weboob.browser.elements import DictElement, ItemElement, method from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import Field +from .compat.weboob_browser_filters_standard import Field from weboob.capabilities.base import NotAvailable from weboob.capabilities.calendar import BaseCalendarEvent, CATEGORIES, STATUS, TRANSP diff --git a/modules/supertoinette/compat/__init__.py b/modules/supertoinette/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/supertoinette/compat/weboob_browser_filters_standard.py b/modules/supertoinette/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/supertoinette/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/supertoinette/pages.py b/modules/supertoinette/pages.py index ad47fe9fb2..8ede6b3e95 100644 --- a/modules/supertoinette/pages.py +++ b/modules/supertoinette/pages.py @@ -22,7 +22,7 @@ from weboob.capabilities.image import BaseImage, Thumbnail from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import ( +from .compat.weboob_browser_filters_standard import ( CleanText, Env, Regexp, Type, Join, Eval, ) from weboob.browser.filters.html import XPath diff --git a/modules/suravenir/compat/__init__.py b/modules/suravenir/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/suravenir/compat/weboob_browser_filters_standard.py b/modules/suravenir/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/suravenir/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/suravenir/pages.py b/modules/suravenir/pages.py index 4a993b0811..51477d5799 100644 --- a/modules/suravenir/pages.py +++ b/modules/suravenir/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import ListElement, TableElement, ItemElement, method from weboob.browser.filters.html import AbsoluteLink, TableCell, Link -from weboob.browser.filters.standard import CleanText, CleanDecimal, Date +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Date from weboob.capabilities import NotAvailable from weboob.capabilities.bank import Account, Investment, Transaction from weboob.browser.pages import HTMLPage, LoggedPage, pagination diff --git a/modules/t411/pages/compat/__init__.py b/modules/t411/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/t411/pages/compat/weboob_browser_filters_standard.py b/modules/t411/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/t411/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/t411/pages/torrents.py b/modules/t411/pages/torrents.py index cdd56b5847..2ef4225c3f 100644 --- a/modules/t411/pages/torrents.py +++ b/modules/t411/pages/torrents.py @@ -23,7 +23,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage, LoggedPage, RawPage -from weboob.browser.filters.standard import Regexp, CleanText, Type, Format +from .compat.weboob_browser_filters_standard import Regexp, CleanText, Type, Format from weboob.browser.filters.html import CleanHTML diff --git a/modules/themisbanque/compat/__init__.py b/modules/themisbanque/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/themisbanque/compat/weboob_browser_filters_standard.py b/modules/themisbanque/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/themisbanque/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/themisbanque/pages.py b/modules/themisbanque/pages.py index 43d99acedc..0603ebd750 100644 --- a/modules/themisbanque/pages.py +++ b/modules/themisbanque/pages.py @@ -27,7 +27,7 @@ from weboob.capabilities.bank import Account from weboob.capabilities.base import NotAvailable from weboob.capabilities.profile import Profile -from weboob.browser.filters.standard import CleanText, CleanDecimal, Async, Regexp, Join, Field +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Async, Regexp, Join, Field from weboob.browser.filters.html import Link, TableCell, ColumnNotFound from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.capabilities.bank.iban import is_iban_valid diff --git a/modules/ticketscesu/compat/__init__.py b/modules/ticketscesu/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ticketscesu/compat/weboob_browser_filters_standard.py b/modules/ticketscesu/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/ticketscesu/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/ticketscesu/pages.py b/modules/ticketscesu/pages.py index 8c99899b8a..be0728fca3 100644 --- a/modules/ticketscesu/pages.py +++ b/modules/ticketscesu/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import method, ItemElement, ListElement, SkipItem -from weboob.browser.filters.standard import CleanDecimal, CleanText, Field, Format, Date +from .compat.weboob_browser_filters_standard import CleanDecimal, CleanText, Field, Format, Date from weboob.browser.filters.html import Attr from weboob.browser.pages import HTMLPage, LoggedPage from weboob.capabilities.bank import Account, Transaction diff --git a/modules/tinder/browser.py b/modules/tinder/browser.py index 960e1e03ab..1d0378840e 100644 --- a/modules/tinder/browser.py +++ b/modules/tinder/browser.py @@ -21,7 +21,7 @@ import re from weboob.browser.browsers import DomainBrowser, APIBrowser -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.browser.pages import HTMLPage from weboob.browser.profiles import IPhone, Android from weboob.exceptions import BrowserIncorrectPassword, ParseError diff --git a/modules/tinder/compat/__init__.py b/modules/tinder/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/tinder/compat/weboob_browser_filters_standard.py b/modules/tinder/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/tinder/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/torrentz/pages/compat/__init__.py b/modules/torrentz/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/torrentz/pages/compat/weboob_browser_filters_standard.py b/modules/torrentz/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/torrentz/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/torrentz/pages/torrents.py b/modules/torrentz/pages/torrents.py index 53f380e09d..a124a59987 100644 --- a/modules/torrentz/pages/torrents.py +++ b/modules/torrentz/pages/torrents.py @@ -7,7 +7,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.capabilities.base import NotAvailable from weboob.capabilities.torrent import Torrent, MagnetOnly -from weboob.browser.filters.standard import CleanText, Regexp, Date, Type +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Date, Type from weboob.tools.compat import quote_plus diff --git a/modules/trainline/browser.py b/modules/trainline/browser.py index 09a2a8cb06..0abdc8c679 100644 --- a/modules/trainline/browser.py +++ b/modules/trainline/browser.py @@ -23,7 +23,7 @@ from weboob.browser.browsers import APIBrowser from weboob.exceptions import BrowserIncorrectPassword -from weboob.browser.filters.standard import CleanDecimal, Date +from .compat.weboob_browser_filters_standard import CleanDecimal, Date from weboob.browser.exceptions import ClientError from weboob.capabilities.bill import DocumentTypes, Bill, Subscription diff --git a/modules/trainline/compat/__init__.py b/modules/trainline/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/trainline/compat/weboob_browser_filters_standard.py b/modules/trainline/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/trainline/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/transilien/compat/__init__.py b/modules/transilien/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/transilien/compat/weboob_browser_filters_standard.py b/modules/transilien/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/transilien/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/transilien/pages.py b/modules/transilien/pages.py index 2ded719b85..9ae8d9fc3f 100644 --- a/modules/transilien/pages.py +++ b/modules/transilien/pages.py @@ -24,7 +24,7 @@ from weboob.browser.elements import TableElement, ItemElement, DictElement, method from weboob.capabilities.travel import Station, Departure, RoadStep from weboob.capabilities import NotAvailable -from weboob.browser.filters.standard import CleanText, Filter, Time, Env, Regexp, Duration,\ +from .compat.weboob_browser_filters_standard import CleanText, Filter, Time, Env, Regexp, Duration,\ Format, Join, DateTime from weboob.browser.filters.json import Dict from weboob.browser.filters.html import Link, TableCell diff --git a/modules/tumblr/browser.py b/modules/tumblr/browser.py index 3e04cd0301..fffc693797 100644 --- a/modules/tumblr/browser.py +++ b/modules/tumblr/browser.py @@ -24,7 +24,7 @@ from weboob.tools.json import json from weboob.browser.browsers import APIBrowser -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.capabilities.gallery import BaseImage from weboob.capabilities.image import Thumbnail diff --git a/modules/tumblr/compat/__init__.py b/modules/tumblr/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/tumblr/compat/weboob_browser_filters_standard.py b/modules/tumblr/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/tumblr/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/twitter/compat/__init__.py b/modules/twitter/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/twitter/compat/weboob_browser_filters_standard.py b/modules/twitter/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/twitter/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/twitter/pages.py b/modules/twitter/pages.py index a27b07a0bd..fe5b190c20 100644 --- a/modules/twitter/pages.py +++ b/modules/twitter/pages.py @@ -25,7 +25,7 @@ from weboob.tools.json import json from weboob.browser.pages import HTMLPage, JsonPage, FormNotFound, pagination, LoggedPage from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Format, Regexp, Env, DateTime, Filter +from .compat.weboob_browser_filters_standard import CleanText, Format, Regexp, Env, DateTime, Filter from weboob.browser.filters.html import Link, Attr from weboob.capabilities.messages import Thread, Message from weboob.capabilities.base import BaseObject diff --git a/modules/vimeo/compat/__init__.py b/modules/vimeo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/vimeo/compat/weboob_browser_filters_standard.py b/modules/vimeo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/vimeo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/vimeo/pages.py b/modules/vimeo/pages.py index e1e395ac20..77fde4c4a7 100644 --- a/modules/vimeo/pages.py +++ b/modules/vimeo/pages.py @@ -25,7 +25,7 @@ from weboob.exceptions import ParseError from weboob.browser.elements import ItemElement, ListElement, method, DictElement from weboob.browser.pages import HTMLPage, pagination, JsonPage, XMLPage -from weboob.browser.filters.standard import Regexp, Env, CleanText, DateTime, Duration, Field, BrowserURL +from .compat.weboob_browser_filters_standard import Regexp, Env, CleanText, DateTime, Duration, Field, BrowserURL from weboob.browser.filters.html import Attr, Link from weboob.browser.filters.json import Dict diff --git a/modules/vine/compat/__init__.py b/modules/vine/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/vine/compat/weboob_browser_filters_standard.py b/modules/vine/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/vine/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/vine/pages.py b/modules/vine/pages.py index 0196e0cfc8..581c3d3ceb 100644 --- a/modules/vine/pages.py +++ b/modules/vine/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import ItemElement, DictElement, method from weboob.browser.pages import JsonPage -from weboob.browser.filters.standard import Regexp +from .compat.weboob_browser_filters_standard import Regexp from weboob.browser.filters.json import Dict diff --git a/modules/vlille/compat/__init__.py b/modules/vlille/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/vlille/compat/weboob_browser_filters_standard.py b/modules/vlille/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/vlille/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/vlille/pages.py b/modules/vlille/pages.py index 35626659da..c575f697ac 100644 --- a/modules/vlille/pages.py +++ b/modules/vlille/pages.py @@ -21,7 +21,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, TableElement, method -from weboob.browser.filters.standard import CleanText, TableCell, DateTime, Field +from .compat.weboob_browser_filters_standard import CleanText, TableCell, DateTime, Field from weboob.capabilities.gauge import Gauge, GaugeMeasure, GaugeSensor from weboob.capabilities.base import NotLoaded diff --git a/modules/weather/compat/__init__.py b/modules/weather/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/weather/compat/weboob_browser_filters_standard.py b/modules/weather/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/weather/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/weather/pages.py b/modules/weather/pages.py index e75db93e4c..375a285dc5 100644 --- a/modules/weather/pages.py +++ b/modules/weather/pages.py @@ -21,7 +21,7 @@ from weboob.browser.elements import ItemElement, method, DictElement from weboob.browser.pages import JsonPage -from weboob.browser.filters.standard import Format, DateTime, Env +from .compat.weboob_browser_filters_standard import Format, DateTime, Env from weboob.browser.filters.json import Dict from weboob.capabilities.weather import Forecast, Current, City, Temperature diff --git a/modules/wordreference/compat/__init__.py b/modules/wordreference/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/wordreference/compat/weboob_browser_filters_standard.py b/modules/wordreference/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/wordreference/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/wordreference/pages.py b/modules/wordreference/pages.py index c32df5a6e1..b669d3417c 100644 --- a/modules/wordreference/pages.py +++ b/modules/wordreference/pages.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method from weboob.capabilities.translate import Translation -from weboob.browser.filters.standard import CleanText, Regexp, Env +from .compat.weboob_browser_filters_standard import CleanText, Regexp, Env class TranslatePage(HTMLPage): diff --git a/modules/xhamster/compat/__init__.py b/modules/xhamster/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/xhamster/compat/weboob_browser_filters_standard.py b/modules/xhamster/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/xhamster/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/xhamster/pages.py b/modules/xhamster/pages.py index 11aefc19e0..fc9d07dd03 100644 --- a/modules/xhamster/pages.py +++ b/modules/xhamster/pages.py @@ -20,7 +20,7 @@ from __future__ import unicode_literals from weboob.browser.elements import ItemElement, ListElement, method -from weboob.browser.filters.standard import CleanText, Duration, Regexp, Env, Field, RawText, Eval, Base +from .compat.weboob_browser_filters_standard import CleanText, Duration, Regexp, Env, Field, RawText, Eval, Base from weboob.browser.filters.html import AbsoluteLink, Attr from weboob.browser.filters.json import Dict from weboob.browser.pages import HTMLPage, pagination diff --git a/modules/yahoo/compat/__init__.py b/modules/yahoo/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/yahoo/compat/weboob_browser_filters_standard.py b/modules/yahoo/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/yahoo/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/yahoo/pages.py b/modules/yahoo/pages.py index 45b3a0e4d2..3189d3c9f6 100644 --- a/modules/yahoo/pages.py +++ b/modules/yahoo/pages.py @@ -22,7 +22,7 @@ from weboob.browser.elements import ItemElement, DictElement, method from weboob.capabilities.weather import Forecast, Current, City, Temperature from weboob.browser.filters.json import Dict -from weboob.browser.filters.standard import CleanText, CleanDecimal, Format, Date, Env +from .compat.weboob_browser_filters_standard import CleanText, CleanDecimal, Format, Date, Env class YahooPage(JsonPage): diff --git a/modules/yggtorrent/pages/compat/__init__.py b/modules/yggtorrent/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/yggtorrent/pages/compat/weboob_browser_filters_standard.py b/modules/yggtorrent/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/yggtorrent/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/yggtorrent/pages/torrents.py b/modules/yggtorrent/pages/torrents.py index a60e0bbdc4..84df0e7cb1 100644 --- a/modules/yggtorrent/pages/torrents.py +++ b/modules/yggtorrent/pages/torrents.py @@ -24,7 +24,7 @@ from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.pages import HTMLPage, LoggedPage, RawPage, pagination -from weboob.browser.filters.standard import Regexp, CleanText, CleanDecimal, Format +from .compat.weboob_browser_filters_standard import Regexp, CleanText, CleanDecimal, Format from weboob.browser.filters.html import CleanHTML, AbsoluteLink diff --git a/modules/yomoni/browser.py b/modules/yomoni/browser.py index 4ce9805119..41243e4a88 100644 --- a/modules/yomoni/browser.py +++ b/modules/yomoni/browser.py @@ -28,7 +28,7 @@ from weboob.browser.browsers import APIBrowser from weboob.browser.exceptions import ClientError -from weboob.browser.filters.standard import CleanDecimal, Date +from .compat.weboob_browser_filters_standard import CleanDecimal, Date from weboob.exceptions import BrowserIncorrectPassword, ActionNeeded from weboob.capabilities.bank import Account, Investment, Transaction from weboob.capabilities.base import NotAvailable diff --git a/modules/yomoni/compat/__init__.py b/modules/yomoni/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/yomoni/compat/weboob_browser_filters_standard.py b/modules/yomoni/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/yomoni/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/youjizz/pages/compat/__init__.py b/modules/youjizz/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/youjizz/pages/compat/weboob_browser_filters_standard.py b/modules/youjizz/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/youjizz/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/youjizz/pages/index.py b/modules/youjizz/pages/index.py index 0a38977aec..169e0f4810 100644 --- a/modules/youjizz/pages/index.py +++ b/modules/youjizz/pages/index.py @@ -20,7 +20,7 @@ from weboob.browser.pages import HTMLPage, pagination from weboob.browser.elements import ListElement, ItemElement, method -from weboob.browser.filters.standard import CleanText, Duration, Regexp +from .compat.weboob_browser_filters_standard import CleanText, Duration, Regexp from weboob.browser.filters.html import Link, CSS from weboob.capabilities.base import NotAvailable from weboob.capabilities.image import Thumbnail diff --git a/modules/youjizz/pages/video.py b/modules/youjizz/pages/video.py index 3555a6df62..d432d6b46f 100644 --- a/modules/youjizz/pages/video.py +++ b/modules/youjizz/pages/video.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, method -from weboob.browser.filters.standard import CleanText, Env +from .compat.weboob_browser_filters_standard import CleanText, Env from weboob.capabilities.video import BaseVideo from weboob.tools.misc import to_unicode diff --git a/modules/youporn/pages/compat/__init__.py b/modules/youporn/pages/compat/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/youporn/pages/compat/weboob_browser_filters_standard.py b/modules/youporn/pages/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/youporn/pages/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/youporn/pages/index.py b/modules/youporn/pages/index.py index 1672ccd5d9..a7eb5f7614 100644 --- a/modules/youporn/pages/index.py +++ b/modules/youporn/pages/index.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, ListElement, method from weboob.browser.filters.html import Attr -from weboob.browser.filters.standard import CleanText, Duration, Regexp, Type +from .compat.weboob_browser_filters_standard import CleanText, Duration, Regexp, Type from weboob.capabilities.base import NotAvailable from weboob.capabilities.image import Thumbnail diff --git a/modules/youporn/pages/video.py b/modules/youporn/pages/video.py index 9654e42cef..4250221862 100644 --- a/modules/youporn/pages/video.py +++ b/modules/youporn/pages/video.py @@ -22,7 +22,7 @@ from weboob.browser.pages import HTMLPage from weboob.browser.elements import ItemElement, method -from weboob.browser.filters.standard import CleanText, Env, Regexp, Type +from .compat.weboob_browser_filters_standard import CleanText, Env, Regexp, Type from weboob.capabilities.base import NotAvailable from ..video import YoupornVideo diff --git a/modules/zerobin/compat/weboob_browser_filters_standard.py b/modules/zerobin/compat/weboob_browser_filters_standard.py new file mode 100644 index 0000000000..f382d162f0 --- /dev/null +++ b/modules/zerobin/compat/weboob_browser_filters_standard.py @@ -0,0 +1,49 @@ + +import weboob.browser.filters.standard as OLD + +# can't import *, __all__ is incomplete... +for attr in dir(OLD): + globals()[attr] = getattr(OLD, attr) + + +try: + __all__ = OLD.__all__ +except AttributeError: + pass + + +class Coalesce(MultiFilter): + """ + Returns the first value that is not falsy, + or default if all values are falsy. + """ + @debug() + def filter(self, values): + for value in values: + if value: + return value + return self.default_or_raise(FilterError('All falsy and no default.')) + + +class MapIn(Filter): + """ + Map the pattern of a selected value to another value using a dict. + """ + + def __init__(self, selector, map_dict, default=_NO_DEFAULT): + """ + :param selector: key from `map_dict` to use + """ + super(MapIn, self).__init__(selector, default=default) + self.map_dict = map_dict + + @debug() + def filter(self, txt): + """ + :raises: :class:`ItemNotFound` if key pattern does not exist in dict + """ + for key in self.map_dict: + if key in txt: + return self.map_dict[key] + + return self.default_or_raise(ItemNotFound('Unable to handle %r on %r' % (txt, self.map_dict))) diff --git a/modules/zerobin/crypto.py b/modules/zerobin/crypto.py index 9292af46b2..5cb45b4306 100644 --- a/modules/zerobin/crypto.py +++ b/modules/zerobin/crypto.py @@ -22,10 +22,16 @@ import math from os import urandom -from Cryptodome.Cipher import AES -from Cryptodome.Protocol.KDF import PBKDF2 -from Cryptodome.Hash import SHA256 -from Cryptodome.Hash import HMAC +try: + from Cryptodome.Cipher import AES + from Cryptodome.Protocol.KDF import PBKDF2 + from Cryptodome.Hash import SHA256 + from Cryptodome.Hash import HMAC +except ImportError: + from Crypto.Cipher import AES + from Crypto.Protocol.KDF import PBKDF2 + from Crypto.Hash import SHA256 + from Crypto.Hash import HMAC def log2(n): diff --git a/modules/zerobin/pages.py b/modules/zerobin/pages.py index b6b53116be..6bb6ca3ef5 100644 --- a/modules/zerobin/pages.py +++ b/modules/zerobin/pages.py @@ -22,7 +22,7 @@ from zlib import decompress, MAX_WBITS, compressobj, DEFLATED from weboob.browser.pages import HTMLPage -from weboob.browser.filters.standard import CleanText +from .compat.weboob_browser_filters_standard import CleanText from weboob.tools.json import json from weboob.tools.compat import urljoin -- GitLab