From 38a99064b0d2e3b01aaa2d0a55a3bc4ab7171188 Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Fri, 21 Mar 2014 08:29:39 +0100 Subject: [PATCH] add filter Format in default formatters --- modules/poivy/pages.py | 37 +++++---------------------- weboob/tools/browser2/filters.py | 44 +++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/modules/poivy/pages.py b/modules/poivy/pages.py index f90aa0ac..58c3a080 100644 --- a/modules/poivy/pages.py +++ b/modules/poivy/pages.py @@ -19,7 +19,7 @@ from weboob.tools.browser import BrowserBanned from weboob.tools.browser2.page import HTMLPage, LoggedPage, method, ListElement, ItemElement -from weboob.tools.browser2.filters import Env, CleanText, CleanDecimal, Field, Attr, Filter, Time, Date, Link +from weboob.tools.browser2.filters import Env, CleanText, CleanDecimal, Field, Attr, Time, Date, Link, Format from weboob.capabilities.bill import Subscription, Detail from datetime import datetime @@ -28,7 +28,7 @@ __all__ = ['LoginPage', 'HomePage', 'HistoryPage', 'BillsPage', 'ErrorPage'] class ErrorPage(HTMLPage): - pass + pass class LoginPage(HTMLPage): @@ -49,31 +49,6 @@ class LoginPage(HTMLPage): form.submit() -class InsertX(Filter): - """ - Insert a list of Filters inside a string - """ - def __init__(self, selectors, string): - self.string = string - self.selectors = selectors - - def map_filter(self, selector, item): - if isinstance(selector, basestring): - value = item.xpath(selector) - elif callable(selector): - value = selector(item) - else: - value = selector - return value - - def __call__(self, item): - myliste = [self.map_filter(selector, item) for selector in self.selectors] - return self.filter(tuple(myliste)) - - def filter(self, mytupple): - return self.string % mytupple - - class HomePage(LoggedPage, HTMLPage): @method @@ -85,7 +60,7 @@ class HomePage(LoggedPage, HTMLPage): obj_id = CleanText('//span[@class="welcome-text"]/b') obj__balance = CleanDecimal(CleanText('//span[@class="balance"]'), replace_dots=False) - obj_label = InsertX([Field('id'), Field('_balance')], u"Poivy - %s - %s €") + obj_label = Format(u"Poivy - %s - %s €", Field('id'), Field('_balance')) class HistoryPage(LoggedPage, HTMLPage): @@ -109,9 +84,9 @@ class HistoryPage(LoggedPage, HTMLPage): obj_datetime = Env('datetime') obj_price = CleanDecimal('td[7]', replace_dots=False, default=0) obj_currency = u'EUR' - obj_label = InsertX([CleanText('td[3]'), CleanText('td[4]'), - CleanText('td[5]'), CleanText('td[6]')], - u"%s from %s to %s - %s") + obj_label = Format(u"%s from %s to %s - %s", + CleanText('td[3]'), CleanText('td[4]'), + CleanText('td[5]'), CleanText('td[6]')) def parse(self, el): mydate = Date(CleanText('td[1]'))(el) diff --git a/weboob/tools/browser2/filters.py b/weboob/tools/browser2/filters.py index d76c13e7..1e5a4d8b 100644 --- a/weboob/tools/browser2/filters.py +++ b/weboob/tools/browser2/filters.py @@ -54,15 +54,17 @@ class Filter(_Filter): super(Filter, self).__init__() self.selector = selector - def __call__(self, item): - if isinstance(self.selector, basestring): - value = item.xpath(self.selector) - elif callable(self.selector): - value = self.selector(item) + @classmethod + def select(cls, selector, item): + if isinstance(selector, basestring): + return item.xpath(selector) + elif callable(selector): + return selector(item) else: - value = self.selector + return selector - return self.filter(value) + def __call__(self, item): + return self.filter(self.select(self.selector, item)) def filter(self, value): """ @@ -85,6 +87,7 @@ class Env(_Filter): def __call__(self, item): return item.env[self.name] + class TableCell(_Filter): """ Used with TableElement, it get the cell value from its name. @@ -119,6 +122,7 @@ class TableCell(_Filter): return self.default raise KeyError('Unable to find column %s' % ' or '.join(self.names)) + class CleanText(Filter): """ Get a cleaned text from an element. @@ -152,6 +156,7 @@ class CleanText(Filter): txt = txt.replace(symbol, '') return txt + class CleanDecimal(CleanText): """ Get a cleaned Decimal value from an element. @@ -173,6 +178,7 @@ class CleanDecimal(CleanText): else: raise InvalidOperation(e) + class Attr(Filter): def __init__(self, selector, attr, default=_NO_DEFAULT): super(Attr, self).__init__(selector) @@ -245,6 +251,7 @@ class Regexp(Filter): else: return mobj.expand(self.template) + class Map(Filter): def __init__(self, selector, map_dict, default=_NO_DEFAULT): super(Map, self).__init__(selector) @@ -260,12 +267,14 @@ class Map(Filter): else: raise KeyError('Unable to handle %r' % txt) + class Date(Filter): def filter(self, txt): if empty(txt): return txt return parse_date(txt) + class Time(Filter): klass = datetime.time regexp = re.compile(ur'(?P\d+):?(?P\d+)(:(?P\d+))?') @@ -293,3 +302,24 @@ class Duration(Time): klass = datetime.timedelta regexp = re.compile(ur'((?P\d+)[:;])?(?P\d+)[;:](?P\d+)') kwargs = {'hours': 'hh', 'minutes': 'mm', 'seconds': 'ss'} + + +class MultiFilter(Filter): + def __init__(self, *args): + super(MultiFilter, self).__init__(args) + + 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() + + +class Format(MultiFilter): + def __init__(self, fmt, *args): + super(Format, self).__init__(*args) + self.fmt = fmt + + def filter(self, values): + return self.fmt % values