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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 dc3a94819a410d7cd7a136b69fc2fc1629292ed4..555b9f8470e1832649a9605dbc5fd4f87fe140a8 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c932571593601fdf3f51f3ceaca9adee406f4adf..68608bf16cf98f502668139abf8e5e66082a920b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b5fbe27071e2c243e5cbd5788869c6d93fcbfc86..341ec3d37188ee4e7c4d71fe7968031a2561a14b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4da6855eb7a31c1a641892258bda9888a0c376d4..7db022564e67f1f368362de27f518def2950b56f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 f5a1f170dfb7d8d80f1b69a5bbab5b7870926c81..a825dd8e785567b1a017a0259d19139737650c09 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 51d9c8f49ca8cdb7501ea58ae4598eee4babf592..6655071dbbe8340d2b4f5800c5f53a07fcad7f5a 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 feeb28bf6def3b8a9cc53a65aadf36aee2ec74d9..cf1b096445570386948b538d17f7ce922ff0b9b2 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 68d191eaeeb0e167834554e302e8947201f8bee1..59aa04e30b31661a79cc5c3e098f84d6e48ff0f7 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2a91cfee57767683eb450c4830a878bd1ada013e..f60c2d2f41f555f2713a3fe0b6f386570a4f9178 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2eca4bcb5a3420702089a3064f9828e23ab207fe..38684cda81d4246ab014740e13c0d96eb622e3dc 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 639e05f6ef71ff979617c929e821ec31563400b6..056bd6790c3dba0a8263b3d0fdc83fdd34fad8e8 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 455b7e03bbed091e774f95e8ded5c869cc4fdf5d..f6bebe51f8865be039af5b3704243f8583d4c8a1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a09ee0104721ff6aa2fc79929954156a413a5f81..ba85a88a7307d2565a972950d3e2fb4556da68cc 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 87002d4cb5b3dfcacc42cd51b20778fb053bca05..31d3acc1a939568255e81bd8bc9a300368770cfc 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 4869c5dd085f2a9254b5654afe53088e6e7815c8..37f3c97bec68c310b67f14de35c8a20560645948 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c1d82a8176f2a2c49ebfb329118ba0fec257cc94..ad2433d25b1695037cc3a8ff3ee08ae2050dfc38 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 b1efe82ce5bb96e503001a773dcaba18c53797fe..0bd8ad196a9a42482ba04f548ca15beef21017ae 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 e4678e5980f1e304b2f4666f843202322b927e57..850cdc0b51828c103fa97d5a30f5daa357cf72b8 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3f2228c8cbad22c70c954b4406b632b18121ac9a..b4319c8347acf9c3131508f35f1479050e9a4af4 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 e954834151716c5234a19ce4fbdc910eaf3c4819..faacf2d9a12d21dc301fd165046374d5f3138921 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 1c479d39f477e3dc0b480facdbcb4a0d59e5df45..9cefbaa66d067a2625099923f22435d21ce283a6 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 1b13f73eafdabc7e3c3d052fbd09ac292e465388..556a0692a1cd17c934bb2dc9c24f1a9f1698c0ea 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 5e3332c106c8c402dbaa84964aeb4890633a9715..5a1df8a02e632ec3f6b62022e4fe3eb7375dffba 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2fe5c673402ccd58042a25d9efc700fb9bd4da04..c19459e74465fefd76e1b8b1c4302a5fb31e1607 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 fe2158464e29eaba64c04b6e9638fa6fbeff6536..c5ca4670eaff7ca24cf3578183254eff01119f60 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4416c0755840d1aefc737938b32e1233a165ed03..4808f235d947d1762ba36d6a09dc828710c0ba27 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e2710166a44c9dca06310953bdf50b50712dd946..4477c5b208abe738ec365ddca8cf44bed6c8e630 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 cce7d9b3b25371027f2d7915d1fbdd1ef3975bde..ae623acf830072b7574a17abf198fb0da17e6a6c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e120ad253aa5685d45e8cf306373032498671bff..d8e669cf21f7c2edb41ed0e558ac01f7237cfbe9 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b00f3a01725cd4a73879a59aa466a5d80f519e6e..cf0bc8116624d1b2ab8a4877ab1553c9bdab9d10 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ce86595c8cb0a5989cd38958851b16ebd9f11469..4cac16d8bc5f28fc30ba9465818318fd723775ab 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 74a80790e0a744104c50aa8107c1fc318e44d3ed..fb05fd303d8700f1da8662a86f3df8b3f5160cd1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 fe95e565dc61fb42f3faa9d0c78398588faf951a..e44394632c1297170ce4ad34eec01483a5736c85 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 791034e86dc90a75712c95ed4f24926b80a35eda..3134affe0b55005355be7cdc3e93d5246cefdeeb 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 5434f42c8163bc63d17ec1772bc72bd45051d4b9..c749db9ff8c48dcb2d85fba4f13455563f4fb786 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 27206674b18089a394942c2cca8e030a715df3cc..ed0d806cead84cab9011428560917b79bf884f27 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 182d600b82fdc26642cdf78b7730251fe49ed1bb..d52dcd46021883a7a65b0a472e5e6ab09d706ec3 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 15f1e5a7fa7c4735731a4ae31ba6ceef98676773..a09f110a52e54d3735607419091dd9d95d924d25 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 aac62cf91d13ed309459148c154a64fec332fe7e..853571165a89a0dfb9a28cf5ed3a0f7951bcdea0 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 bb3901bc3119beb4ca9f5e21916abc5e5f1309ce..ad76ffaf7fc3e3180fe350518503738c94ec3149 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 a9db44b4ce110a31138ab62846f1bef0679e03bb..7564f5909f6838ba2cb5966921f7e98593db229c 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a2201074e3ac07230fc1ae745af822e7f9a7dd88..29d355e005c399a17c9210ff8c052ce0de538dd6 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 27e32b356d3ba9d7f8a41b6f5660c287a156c0d2..9503920c9dd2b2b2436934054d3f07b04a1ec3da 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ddfe94cd0e586c0fc6893d7568741388cf8f9671..d2a6d76c06b07bcb5e79d2d51ebe7b2e06ee5f69 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 a9b296dedb4bf9f53c71f12cae76080cfa8537a7..e075b7c4b6ea998c77be25e7f3002659636d5e21 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 67ca55b7394fee9638dbb19ab8fb04938f9f13f4..83238a9d91bb4d09238da74467cc7aa59d92f9c5 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 351bd2aea3f49e6f0f10b46a8446182559fbb5b0..55fd793a4ee515be1c8fb3dfc24b421d6d3f5046 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0f2bbdd5b593d8fd76fba05f8c62e6320df109df..cf339e0dd0294cc1dd272c349d6c65ca6a1fbf19 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 84eeca9bee7d4cfbcf0c6ae5c4d7f8d13dc24321..5c9976ec637b8694506912d7d09f378196406821 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 f80e4a9b68c93638e2226ed7600af74b964c8aa4..e9cd4d1d87981af05c1ea22cb86a0ed6497218fe 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 f97b9d1a88888fd0ed55135b6c76c41d01078f69..c51140b51ecfb324eb44862ecaa86fb9b7430ae1 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 8d71ee1924bb5181d2405d034e1207c3401c555d..185dde5e72bd179bfb5c30c6e9ddd86e78cbaffd 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e2a5b719dccfbfd5d399b3fa239c3ce12e9fb7cb..03536f12d53d8eb12146bc07e07b13e31e9f136c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ce7c88cabbbf988b6a410bffa6daeae143ae3317..a070bd8b259c2e23b0f71188bfb52a39cb782924 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 aaa74b64f853f9c2c85d2555d618b4ba1a483aeb..1e068e9d523b39de197a47a0ca98f8b5f372c5ff 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 67cc5a70648dae58171c42068a4c42ede74c60f9..cf98b59cbd1892202ac5b326f64ce43f40be5687 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 2905abfe42d1c849b35b8514d13c19ba28f1e4ef..4df46b8cda32baa98776df00264c098bd57f701c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 15f44efc2a7d627f149d2cb5189fe649055bf050..d01099ec52ccf8700265fe7fef3f36417e1474d8 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 01789ae4cbdeb0ab30c659c24e0bdfad054464a9..541feea84f6ec9e178e231702909f2f651a37fdd 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 cca52b6d06e1b8b1969e7a2eba5c639a57abf3c8..409ce32cb1e3ca8fcef215a6d3cab9983c79fa46 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 da9752d265b6b24c2827efe4730d61ef9cc0586c..fbda8b46bf6d824df110b765562c7c5ff657e71f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 f05bbfdbeb06f3bac741495769311e0bc1d6fc93..2bec02b92c969c8f53e0a51ca9bdcb3942851832 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 270c342443db3f555e9edbd5a165173e1623f135..33d30274745378e54b679c4cf52e6aecf6fb6e2b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a80a53be0023b5105c91acdc9817d25d03d625cf..e5aee8bd81efcea21f6fa3d8150baa4cba9d3f48 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 8b49294943ad8718b4faf6673d7a6f779946d1a3..948eabeda7df3d1fdf7078622146662459293ded 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 df16bfdc726dec72fa69587eac429741a115c073..8216b0b47830e7a14e5033e31fc1fb4bf246d25a 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 eea18b7def0040f82ecd01d5b99a24041908b71d..832310a82a07ce78c868e577a80e04d7a934705e 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2486b0f93065c77d34285351dca7a374edb67897..46127d19c105adf2d96634637e9a40246ae01bf6 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 0d227aab30fc02f097b6790e301031ae36fb959c..d92839f719489ec770331c1b5263cafc5801d7ee 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 9b0b429ce50d6c55f4378f0bc7cb19f7e16b8790..89748dd0e5daab135c497274b0dd817e933a6b99 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 ae6f7118dd47ff6d16a43a52f5b0d80fa783246e..cd76d41361f27558ebdfe7ee683bdee70101662b 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 39f6eaebcd1f4ed83c70badf063ff89278dfd5d6..f382d162f07989986480f1ac6e229c930e1b4879 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 27cb8fd4ecd73a929f9371b2a6dd3b2e1219edfe..0ec8bc22f5b4baef46daf8768a9f110cadc84dde 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 4447d38b2849125d15db978840da57bf7ea2e083..aaf4e313b460bb60c7f2045bdf256982c4700b8e 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 5fe416e43f9b3b36ba287e4641180ee43a7afb4b..b9c5019b5c28c5d6288f9897f4dff5f507bff214 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 8153266bd9ba39d087663b09280b0854b2bff39b..464047da38fb47aafacdfdd22c870a1edd1c5445 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 73e2f520fb2301c03a6a71f602da96ebc17a44cb..21f676498693d69eee372927d5056aa0ffb219a2 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 d677c133939feac2cc58539298276003530b14fa..70b99df03af1b76d97b97f33e4e5566354190b1d 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3f29ddc260e32a22d2ef82d8d15e13bc7f9e6add..0000000000000000000000000000000000000000 --- 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 0382f3f4d71ecbc323e84f7f9eb5e0860ab13cf7..e54ea1b56a680847c764e43b79a06e3adfe2e7e6 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 80710eec78918cd936c823b3378f381d33d3aa1d..be2e24cf7c54269c2e5b390e020c9fa6dcbe724e 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 f311e236e44367d5425b03cb57e2ed1059d20a27..bd08936f29f5bdcabd48017841bf68bde1b4ca86 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 73099f175722133db2118831bb345c273aa5f9f1..fc06f6157ed02c0f181910ab5cf918935ecbd764 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 01d72772c5544760e409ffe8c12bc8c0999ef24c..d131dfc4ea5c79944bbc7c5460b69aa3fc2a1cf7 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 df85bd16616c3abfd84a16d1685aed9fb38ff3e4..ea7702742eba9e20f217f400ab8829f4fe7f445d 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4709640589399cb3c685face1ca771cb2406df95..a4bd2a94310eed5c85c1805e73e3c0b580beeb2f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 af113d2aa3d94bb94603cca7fe6ccba9ca1a0fbe..017bfdc8c964eb48d8277aee63232c4861586afc 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 d13f26613a775cf39bfca997564455027f20c9f4..1cb24c4edcdbe9763a54aa458f67ceec6de5220c 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 557ecb1512202c80127b20fa0df74feadc157f3f..8d3cb0580a4be07458b5573aa228404c161f2de4 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 7cbe5fd7bc03c4b41be80e7617371f2d7560f028..768fef16813fb676d0fe5ea6ae2272e355eb783e 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 1476b20206474ff3250ab41e621db105458c5156..b85c23ea4f3c802fefeaa9c46e515f3f0d252cc6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0bfcee0f957bd720621337ac89f6bf92c65f1553..2832fdcb4c60d2b191930c14b662e4b4432f451c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 9518296caba8a91d215777bed27073c93308bbbd..fcc08e451f8c1fd6b41c7b69f47bb10b76df9bcf 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a0748bfca993c11cbf5199e12f43780a166b584a..52b668c814017be721a0cba0b0d0881d8587b7fb 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 35631b889b9ec19d4cffa8e160436072eb644be1..dcbd37d5716e34025792cb363a676d1e339f7471 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 41a4abfc08b25e137814e6fc04f4bf70dd67acd0..fb79d8724f5e99e0372a61c3f66d2db355ec7edc 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 ea1e27643811d442b2a0a6ae188a419477c5f365..ce1255812a12d0c130b3530543cd312545c1e9d6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 5b74c23b273701f96bb9fd519b03ebd5a7f52ef3..404f2af848759961b91efca0119a9a34c9d3a51c 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 98ab18fe96a7a5b8542eec5afc7d9db2d4b03d89..1e997bf0ce6cf60ebd45e5e1cf5d90cb5a178fb4 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 9ae95a975a37dcf9ced68058948422681ca9e299..86f2d729066b6d7668b162ad6cfbe317cd71773f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3b177a59bea48cf0693ddfdf20e70cef8aca0b09..e034cf49cb57fe1fd4672fa60615c34b7e771b32 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 85170e1673393708cbd64497d59c1ee6debacce2..60a12e0a57b6e93a1c12354e97b4424bfc128571 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 8ac50651c99a8f73261865762584602a6ad23a36..c29ce845d47d24aed2a58d485e1d6614c9e552da 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ab890caa2fad8f15ae51501785de5e3b7664da8a..6878af25ad93e27b7fa990b32b7b414a5cfc6c28 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 5117d82c8de1826e452708c65b639b0ecca9522f..adabe17d3f20ca30ed54714a3bff888a67dc68f8 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 999a4a4debb5042bfe023970e41179705dbe3a60..613b06198e0688b4bf0382075f8a591d0f2c3451 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 7416392aa754a269e6da67c5ecef3115a5dbdcb8..619317eda7ab5530cf9257ee4f6d4c62d37a84ce 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 840347e21becc1c2d942f460062a95f114ca486e..3972906e1c0e79fbde9b228994b74a78f3cc7761 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 6bd10c1876ae29199b4b351ea06d05a62bb1b48e..acdfa8567cc3778b04bea00aa0f55625d2f1b2df 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 f7d509f1cb7b686d05c33367a38aaec53a6e9304..387d1caeb4056e4563e121ecab2498131fb98195 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ecbaeac01094eb410649ce3153c5fc15581e4a20..eb58cf5bb28baf1840cecfb1a1f8dc00e78ceb5f 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 88af5e5a58c3ac84c247d4b65b4e162999f0b872..56cca8196386909507ef21100df1410f21caa542 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 225c5b134dbe7b9294ac635f18176d983f9d71e9..43d94b0483effbf68fc73bd85f65de83b2d0326a 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 9e1c2c24431e7769d0cdba6e812e517b92cf1138..66be84e87bdc0c61c8581e8aa6278714f92e08f7 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 f923b66f69761e37735cdad0ea1d3df961a370c3..4cef4ab322e7975099a143715b26cba9a3045a68 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 63147b3d73a0bf83b4e7233a41f065f477d519ac..66a7276dcbd93197a1b914aa4b65054ca937ccbc 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 0b1c2856cfcb80a77854054ad9a4c613d881f65d..907660c470adf507087d3d90fb4fbcdb9345a192 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 49ab713c8966fa06a7485bc4be59685de9633a46..97c8e266405f49103dd93eada5fe14c8d42e6b4f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 997ac6b834a05acbc511383ffde8b77fff4c8bc6..c9b51420f3a798fac502a7b449a7571c5c015874 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ad8390357c70890ec0ea1378dfbafe1bcab35d47..67acf1d18f5500c56c004592d47fbb8de0e7e791 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a79907f5dbdbb50fbcbbf453532340c7855eb756..0e174105dce02c34523d3ab9b68081f72de2c865 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 00efd00786b44f4b61b359cdebf47c841d57b639..68eba2a64d6e8a4eb668d315f31032ebfe19873f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 91dac5ac654a18055b925e731526e98e12ce6cae..9e4ebd144fdd89271bfe2174f2833f480346c1b3 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 20f4367cec10fede14677756afd8fa88143f96c1..bf04caad730ff9c957d35749604ee32b5fd3062a 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4472f386bfcd925a77af8b2b74ad6eee59ac9a9c..21a8661c4235715a8bd27b292ef8c2e7d81c2dd5 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 c9349bca105419f74cda2a6ae8abbd0150987223..c3dfb0def0bd3c08c2398b28262d19e00494f902 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 3e5fbd5a022f20e929114973a989a1e0b5fb7e31..416969c81e2a56abcd89c45b9d719663f7e1d6d0 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 41fd423380dd5e626c503edec3ea83c5ccc2bea6..0f24474da94e697ea58e640e019d1567deb714bf 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3f29ddc260e32a22d2ef82d8d15e13bc7f9e6add..0000000000000000000000000000000000000000 --- 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 d0879f5b45db2c60e73504aebef6097cd32854d5..1be8b6388086a3e5b6c9444aa8dabef068627456 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 bb02e8b047f93ccc371ec4f9b73fe27fa57cea5c..9278d9e62d50ff2a3613e39fdd6e9d46bbcfa6ef 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 452c6a92afe2405b608edabb5ec420c564c3bc5f..8864b44148cafa37af85762788f3d8279d0b31df 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 01ed8c84b4660b8497ddb5578976fe1eba651cdc..1bfd94eef440293fbe2cecda982820b8c00dcf6d 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 0a2dcbea693699a501a0ffce258c97b3ffe8ebfd..9896e285fbe9897f8cec0e1177d1eff968659da0 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4d0234009d71dc338a74cf2c5eff2c8eb09e6d2d..e55dc1b07bac37774256a034a2a4bd06ca458c28 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 a1fb39e4b1033d2fd49abce31294891d7d4fbd84..ffd7a20c9d2255e40d5c1818326a89dbebe186a4 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0a81526f2a1aae990841e109fb6c1dc63dcc18bb..9808c53d81bc11f37c5ec5c6f3cee9ffe9b8c983 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c0b3a36f84895f5616edb4320dcf99fc4038d5f0..b7e79488073b9d90844e3817a6c47ae0139624a9 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 5a17debdf7f8647c9beff9cb5a822e93893ee5e4..0290f3d2df373c96a20f7d78f7099509649fbe3c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 05a89372529a51319f595cff4eea006949578ce8..483e4fd438c3f8a35e5ac6102416b2435159401f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 6281b1e20d74166e3a09c1408cb4874bbb40fc34..aa2992205358a87d1b8ed370dbeb54b2c250ce7a 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 5e46c80132e453c9ec326091741704b7e73634e4..d69af4c47dfe801142379ab90631c151bfc42a69 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4698364d84af0c83816f5b4d705437725084d3c0..fbf47ba683b99d478c13c71c17fe467f89672b80 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 7813ca0dafab38e1ebf15b3c8f684fbe27c6e92a..bd6175510424d396f53468afadd0e5211a533a10 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 147ada6e5cce7559d5f505e09a9c7a9890d7a39e..a1579de84e3433588799bd70e1f58d599a578327 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 1e3526d951138dcdd296163181d18d877fe83bae..28379ea1a9e28e7a97abb5ef5a237258efb27663 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 9e0003bf8c60e1e5c739131deea63db7a435130e..977a0ab3436d2dcc26157e87c24bf216ac5ddfc6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 9005f464ee39510c49b2a55822a5b7c3d710cbcc..7f09fde875d21cf6a9a636200df6d8ffea216cf6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 483abd12a846668b9abf00f0aed09666d070b00c..8867e73ec9f3d2ef98fef4e35699dd4b5f22a284 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 79df9bfdad1ba12587a4d1dca496cf2ffe234c7d..09012ee172bc74a6cd2b66f5ea3226a7c3328aa9 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 dc48030a587707dd54d1a28cc71670f491c10f8e..b85487ab1261bd1c69724f28ffdb64ff07d7d842 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b0ec69defafe5410c97c636049cea0e37a5b010f..9f26d7660f29a52c818629a784fa4c830cf6e68e 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 679bcaf0ec077e954c7e24baa0b7e048e80b73ba..c1fdf50e2d5229578ac036c1c928ce249d90a14b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 5545be5cd76cfce57a2506b039b639abecb0f8b0..c5c1bc6ef50b24ead57e6af43a6e520e8aa4a0ac 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 37edf68c46388707cdf6da6a737dfce9690d573c..9d147977dd8a44bb1f07ed2179a20c4934b21ee3 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b394c12de1231f4ce4b2c3ee3fcd3ade47dea16d..7693c8c8af5e8242a571458b9e77e62a0c4eeda2 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3e60de6213c08fe8d0bd14999022110b642ed695..4b9b93f1e0c545856d4cee79323f34c4a48a85b3 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c7a3ee8b8c240e393c2b1f5df6f1941710b547b0..655ef00aed5af3b6a2b40bcff69de7ef1ab2f588 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 6c997b808b8b922ba65e33b9a87a23a41ac9f0ee..5dbcc10c6d90b729463e73abfd1e6b202527dab1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 fd2744c6901a66392ad84093b074fa7ee01724a3..e6a2a1c1bf5d13554fea45caf06beb2bfea67419 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 d7957aebef674324ae13046583df2b5c29428777..123b57b6241bfaae9ec74b7af41b3dab1e5850ff 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 64797d2420407a080b7fd560c11ea23ecdeefdb5..7d6ec24392fbde493bb30d12fc508c81b5b12b95 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 36f0fb09ed2884925e96516d813d4af0ea45c079..129b7582d3a850d3ccc4485c6b0f72a537d76525 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3f193b1b3d32b3383f6c380cc15080612422e562..db9b724efddcbccb3a9880824111fc3282c57ddb 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 7954d933ae51f20346e156ed48c701a55f3220f8..2c88b9b8ef5a22b1b23fa73bfc93e71110603bf1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c882938ca896227e2c5fed2e5104d09f6456af63..ee2ad9b2e27242816f1b1a7f6461871f9fd71cb6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 bbe59009bbceafcf04e311746a62aac3f923476f..9d2499aa3edc9ba768b74475ce59ba4294b895c4 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 696ffba9e3b410c95ba26ef8c8e6dbbc0d735c89..3267f375cf14b6154a6e2e868ff1c8714edbf0b5 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 256ff9ab185db4515276ecfb150d0fbea07ff625..e62cb3e2b55c5f87c647602fb152065e584f5d35 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 3372f2a574e2b8fd81aee09a5d1670e890317171..e77b4561317f32d5771126d4f16ed070b23c206b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b8c63f2b90576327c40134ccb2a41fa09e1b7917..2fe5a9ff0c5b84a6214a4d912d69e8b36e71698d 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 74f437db64efc4cf9f03f372ec00a9a02b74325f..4d99bd5cb27a5a3084332926abf49563ebc6ebfa 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 77ee206a87e53b07a746a9b53f564b955a44e00d..a7639d3111e0e9030db375fab0185dac660a6191 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2e2b1d18809f986db0e61d827a2023f2258d5f3b..4bda84aeeff27441db26d8b3959ae3ab3957a534 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 6987162d165d51fd6a5c46b970ba2ed11a549421..ef4382bbe9bcfc196ad784dbd7ea3b1cc515a0ff 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 f40ce72cf649f2cae01e0913e28666dd373e02bb..1b9b39e9afecd5705da1f611b500c55d7007c68a 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 15db5e63789fb5e78a8a8b25d2af8f1b0e6f8f4f..a7f5ee4f532146e391507887673803ffd31f97cb 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4acfaca27e541105c68d75ebad7cf9ecc1a50b29..094b50d90419b7b9730bd8cf369a5b7e99e34404 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b19d79998ac7e4cfc01cc7db3153ee1dbd9242bc..b483774d9e84a292c20f661ad778b6724e88968c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 7ec3fecd804bea4868747b922369cb5e326f62a2..045dd7d084da845f71aa8287ce802fdb46a883b2 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 d9cc37c47edb486c201e542762e94d3a6ab4ec8f..08eaef6a000f480e1551f538cbb517c5eddc9f31 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 76aae259a283795c32ad26a6b837a404bdef61bb..bc3365d703394a08bd763e9a9a536b070ebf1805 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 8fe600f3cf94d3f5029bc025d3b5b4ba6130bd95..52a2a34439a0b9199f6709ba06ec76e9b68ed249 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 376c9a3199d4010c53d0adca8bd27135b541bc98..66e58a0a49fd9d4a751bbfc875b6a3561b23fd49 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 db6b79833e3db291e9e5cb9bea41797c06e26f46..98680612760ed9f042a1c624413fceff28622a38 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 6eb6783712e52d993685c0aa2f9f1eddd3caf666..792260046b6a152e777bfe72657512a22862e2d2 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 7f5339dd07dbf18874c99b8c2f1f79e5c3ac20be..6023cbdd54d0098dd9b8d52097f30f6d47f79bd6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 15afecfe62507f8fa983595a958220d30dd6d6a6..0c896d13413f3827f6f3b08851a96865fec2644c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b027a120bd813321d57bf329d16b531cda82e7cd..c9d057d295c2bcc7546b683051a379e32ff0d5b7 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 df4423af3ef5b5937ad993aed1f6da3484bd8195..d9f0e9bc094e42b22311a4055f69d69b76efd1f4 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 65af6fb265e567e6d7c3d6944804de9073438778..bab99587f793c41dd9975293dfb24c6a55173f0e 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 42214cdccd629f9feb88abafe45f314a34cce663..81d0c87bb75892179ad6c63674625998851e4659 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 00bb95426c01cb9aeca405025e11ef087d12e078..f62e0031f5f2c5e695246bdec8a7dfa8990d23e1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 17a0833013e8e0205bd82610a4165c48e6302ccd..d0aafdf50abb156f10de944c2e8d8b34edf0b950 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e01000c0c9355e761129739e56758c35123f6874..aee74ed6eda007860a7b4c0ceb2f10cdda1fb3b0 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 7313c07143d64bc528b206163e8d3a00f0fd0dc0..fb94557a2caf22f8dad576ac240479784bbc5648 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 d7ae47d70dcf1a48fad450b6c1dc8392ccb6a859..d95190020fc847069e9acc8cc596e112e0aeca12 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 db8dedb9133d73361d566d0eba6ef3a95c9ffa74..4102088fdf86d024c02d3eac1d63b0a55b754929 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b13adaf2fdba1ca0b8e3cdf818382bc6ef123457..e0b8624ceaf94602bb10ebe85f615b3656849358 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 cdc9f195ef7be9cf7070ee76fb44f4022b6dc6e1..47958201c4be3a25d695e57343bd97bd8c4b7163 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 80b89611e6d62bf5f00627a2863a11591d2d600a..74766d825cad1b58aa1c27c52e3b4f03b1490af8 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e2c2e25164da8146dd63195e08e78d559a3d4f49..bcd325a25ff9c35b84904398156ef2d384718038 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ea62cc7514d5637d2265de5b29074efeef2f5269..73fb2dde59f918f6c43cc63d11fffea8ff105f05 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ae11da59527f90ce66fdfa83e7bbbd7e2d818a87..49092d049e8d7935dc73cfc4ab1aad0d7ef192ba 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b9394d2ee0a161711d93d20c323d27a6c1d1df55..f1dd222a9a3e85c63c48b92dff505d6c653ae821 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 cc39e133707fa8061901986cf2f8715e87568e4d..ca20f176f5703ec5b37261dc6929ced9664c0236 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 5f957707ffd6c14626f1089278467a40d6f6c856..09f4aa885f888a9ce551d7dd7942ecd50351cb50 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 3719df03d415c418a69e333f74c1116770501c7b..c47a7b8bdb93fe30d5c747fb799fda0ff04bbe41 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 50d71f45545bcd99d31bad1bad9155d8c1c3d9b1..5825debd7a1d8eb82d02a411825334163403e352 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 50c96013bb7ee4c5ce7c4ba077f70df4f4fbba73..d0fe998fe06eb86eda40b1c40f95c62459f53f6b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0941f87f67e81063e458a2522392655e2d9c420c..4069cdc3e470c20ce5be80470c6832034571fde7 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c729cbba71f8adce060bb37135ff4eb2c048241d..914d3b856982fc5728d61a2518c83e3b0ca2f5fc 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 67ffaf2afb4b4dc3f495d0f7c78a169661fe9ad1..e7bf32a0da9906bd189524dbf4d4124df8c6cd61 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 0028a6fd5b1d6eaa025659bb588a1d6414cd1cfb..fa351a6d9be8a0c01cef7766bfb7a475e6f6f5cb 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 2fcaa3aef13420a3728aaed17ea6b8978dfc86c7..14f422cc325b25a11fff29dcf1d61e631701324c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 b137d295a5f34c389d6b220c03c49ea65d211f6b..526cd3a1c6bc8ee77a05e30e3b2b519ce3b493da 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 c8844dd3f76d453b937fc3d4706a0057609350f1..87d299e503d748546573f0f1e5080fac0e8bd335 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 c724c5a3993ec7dec7645b6aa541a2f1addc11a0..98fd59b745c94343040737254917485ce20ab139 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ce9d67f7dfefe14fe653d1d7299b3d59c59721c2..0f273d6157c8db93ef4f8e4e5b6645d0ede9137a 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 df869fbc00be17fde1994f735ca9510060f4fc5e..86ef8d841dedc83669335fd4c3d178e3119536b1 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 ac4052a2c110e41116c5167446bb856bc6b7d11b..321edfed6855255fea87e69533f268d122991c14 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 04f1bcd6dbb6ce47bf5e00d7839b3e4a70cfe61a..ec07000444a5b331e858b7b5102ae20efdb841dd 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 9df2fbee7ad1f22bf3694209708ce4bc0c9b928c..0fd87443c33516fdb197d7416c2c5e7931603c1d 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 016665b88ebbba03cd1682431e06150924c51e2f..9f24afa36d3141ab32fbe8f3bfe1c74f8de63d56 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 35a56697d9e6b861b37935d8d0b1a112543e2b09..3761648fe005e68763087d9635928ede0d5780cb 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2bc892ac10b6f4ea25f711bc161f4f923bb8cb0c..93550b9928edd88f7192578be09cf6c59df0979c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 ad47fe9fb2084202718d9b70ddd02b1a4b311998..8ede6b3e952ee28c8815ecb88306d5057c10730f 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 4a993b0811e1ba364fa033a83c0ca7eb12a6159a..51477d5799e46ad4e4a85fb785e14cc09f535ce2 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 cdd56b58475976a5f5dd13a2c2858766dcf2c12c..2ef4225c3fcc63931021b558610d11980762c286 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 43d99acedcbb9639c79d675059a6cbf14441721c..0603ebd75049001359c92589cf9c1acb7225ceb0 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 8c99899b8a9da2b14a1590c5de22e374b285eb2c..be0728fca351633e3eb2872b19d0d448bbcd8f67 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 960e1e03ab1efc4cc13e22a9b89d651b2efb02f1..1d0378840e9c59d197497bb70125804c873140dd 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 53f380e09d99308446c7909c9763e98444dd2d92..a124a59987ae0df3f18ebe7f749be9a84f8af4af 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 09a2a8cb0697e39fa49f96e9df1e94195157fd3e..0abdc8c679f5a08783636f6fe0e7d1b59b71f754 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 2ded719b854167277719d7fa80126dc8e93f74ac..9ae8d9fc3f398adcc6749e3077f9b4afebe70b4a 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 3e04cd030115f4b8f4b25270cb180f37b96d677e..fffc693797e7281079e8d2b8a7fcbe35151561a6 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a27b07a0bd4bf03a0124333a8fd91108ce1bf3ca..fe5b190c205fddce163cb0493b8a7b1e81602e56 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e1e395ac20c57d3d733e4fb3a441de5abc154de4..77fde4c4a7336d333973b43b0a12e3e04870177a 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0196e0cfc87649c38e5714cc7feb10a1e917a22f..581c3d3cebb037c9558940e64f7ca0b89e522a77 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 35626659dad8f3e8eca5cc7e0558930fc97e2c6d..c575f697ac04ad22fd091c0ed7194b3aa14354a4 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 e75db93e4c6ab8b3097a2661c412874b72662d9b..375a285dc5cc6bb012daa312cde84a6565575939 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 c32df5a6e147f71704f289aa63727521d4c15e52..b669d3417ccb884087ccafa7831e762ad0e53778 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 11aefc19e0d7a67fec06b181ddf3f60d44a2a38c..fc9d07dd037151ec8d9b4b5e75dcaa666e8e5c73 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 45b3a0e4d22d03dcbef2ea023bc68dd3e15f51b5..3189d3c9f6d5e05a45166353e03e96e3f436a4dd 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 a60e0bbdc488d511bc1667feb31be153f87b895b..84df0e7cb17f79d6c7ab9c647bebfda724f0bdca 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 4ce98051191c2a5614487e691240d0450136fba0..41243e4a88c6ddea7ef233463a4db77974eff75b 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 0a38977aec9abdf5ffb20076ad2a53b9fde7bc71..169e0f481058bd490697b3108d6a00999007538c 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 3555a6df62e9f49a977379277d18272d02b02cc4..d432d6b46fe58da4e1d40c9fb72c5506331d99f1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 1672ccd5d9993983475b8afd30a308b190278433..a7eb5f7614ef589a6bb38954a14c87ea3db0334c 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 9654e42ceff38e233bd2265751b0192b9a89474a..42502218626404846c73dc421e91c92081fff9a8 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 0000000000000000000000000000000000000000..f382d162f07989986480f1ac6e229c930e1b4879 --- /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 9292af46b210882323e7e058b05b7c823086dec9..5cb45b4306e8feeb4025f8795fc1f01b47bc2bc2 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 b6b53116be58cb9382309abb33e54b808646cfdf..6bb6ca3ef501246778425bda15a5948163c54b2e 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