PEP8 style fixes and other small style fixes
I used autopep8 on some files and did carefully check the changes. I ignored E501,E302,E231,E225,E222,E221,E241,E203 in my search, and at least E501 on any autopep8 run. Other style fixes not related to PEP8: * Only use new-style classes. I don't think the usage of old-style classes was voluntary. Old-style classes are removed in Python 3. * Convert an if/else to a one-liner in mediawiki, change docstring style change to a comment something that wasn't really appropriate for a docstring. * Unneeded first if condition in meteofrance
This commit is contained in:
parent
1e000acf3a
commit
006e97a8be
99 changed files with 441 additions and 350 deletions
|
|
@ -298,7 +298,7 @@ class AuMBackend(BaseBackend, ICapMessages, ICapMessagesPost, ICapDating, ICapCh
|
||||||
yield thread.root
|
yield thread.root
|
||||||
except BrowserUnavailable, e:
|
except BrowserUnavailable, e:
|
||||||
self.logger.debug('No messages, browser is unavailable: %s' % e)
|
self.logger.debug('No messages, browser is unavailable: %s' % e)
|
||||||
pass # don't care about waiting
|
pass # don't care about waiting
|
||||||
|
|
||||||
def set_message_read(self, message):
|
def set_message_read(self, message):
|
||||||
if message.id == self.MAGIC_ID_BASKET:
|
if message.id == self.MAGIC_ID_BASKET:
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import Image
|
||||||
|
|
||||||
class CaptchaError(Exception): pass
|
class CaptchaError(Exception): pass
|
||||||
|
|
||||||
class Tile:
|
class Tile(object):
|
||||||
hash = {
|
hash = {
|
||||||
'bc8d52d96058478a6def26226145d53b': 'A',
|
'bc8d52d96058478a6def26226145d53b': 'A',
|
||||||
'c62ecdfddb72b2feaed96cd9fe7c2802': 'A',
|
'c62ecdfddb72b2feaed96cd9fe7c2802': 'A',
|
||||||
|
|
@ -111,7 +111,7 @@ class Tile:
|
||||||
print 'hash: %s' % checksum
|
print 'hash: %s' % checksum
|
||||||
raise CaptchaError()
|
raise CaptchaError()
|
||||||
|
|
||||||
class Captcha:
|
class Captcha(object):
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
self.img = Image.open(f)
|
self.img = Image.open(f)
|
||||||
self.w, self.h = self.img.size
|
self.w, self.h = self.img.size
|
||||||
|
|
@ -152,7 +152,7 @@ class Captcha:
|
||||||
s += tile.letter
|
s += tile.letter
|
||||||
return s
|
return s
|
||||||
|
|
||||||
class Decoder:
|
class Decoder(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.hash = {}
|
self.hash = {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ from weboob.tools.ordereddict import OrderedDict
|
||||||
from weboob.capabilities.contact import Contact as _Contact, ProfileNode
|
from weboob.capabilities.contact import Contact as _Contact, ProfileNode
|
||||||
from weboob.tools.misc import html2text
|
from weboob.tools.misc import html2text
|
||||||
|
|
||||||
class FieldBase:
|
|
||||||
|
class FieldBase(object):
|
||||||
def __init__(self, key, key2=None):
|
def __init__(self, key, key2=None):
|
||||||
self.key = key
|
self.key = key
|
||||||
self.key2 = key2
|
self.key2 = key2
|
||||||
|
|
@ -34,18 +35,22 @@ class FieldBase:
|
||||||
def get_value(self, value, consts):
|
def get_value(self, value, consts):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class FieldStr(FieldBase):
|
class FieldStr(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
return html2text(unicode(profile[self.key])).strip()
|
return html2text(unicode(profile[self.key])).strip()
|
||||||
|
|
||||||
|
|
||||||
class FieldBool(FieldBase):
|
class FieldBool(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
return bool(int(profile[self.key]))
|
return bool(int(profile[self.key]))
|
||||||
|
|
||||||
|
|
||||||
class FieldDist(FieldBase):
|
class FieldDist(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
return '%.2f km' % float(profile[self.key])
|
return '%.2f km' % float(profile[self.key])
|
||||||
|
|
||||||
|
|
||||||
class FieldIP(FieldBase):
|
class FieldIP(FieldBase):
|
||||||
def get_hostname(self, s):
|
def get_hostname(self, s):
|
||||||
try:
|
try:
|
||||||
|
|
@ -59,6 +64,7 @@ class FieldIP(FieldBase):
|
||||||
s += ' (first %s)' % self.get_hostname(profile[self.key2])
|
s += ' (first %s)' % self.get_hostname(profile[self.key2])
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
class FieldProfileURL(FieldBase):
|
class FieldProfileURL(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
id = int(profile[self.key])
|
id = int(profile[self.key])
|
||||||
|
|
@ -67,10 +73,12 @@ class FieldProfileURL(FieldBase):
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class FieldPopu(FieldBase):
|
class FieldPopu(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
return unicode(profile['popu'][self.key])
|
return unicode(profile['popu'][self.key])
|
||||||
|
|
||||||
|
|
||||||
class FieldPopuRatio(FieldBase):
|
class FieldPopuRatio(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
v1 = float(profile['popu'][self.key])
|
v1 = float(profile['popu'][self.key])
|
||||||
|
|
@ -80,15 +88,18 @@ class FieldPopuRatio(FieldBase):
|
||||||
else:
|
else:
|
||||||
return '%.2f' % (v1 / v2)
|
return '%.2f' % (v1 / v2)
|
||||||
|
|
||||||
|
|
||||||
class FieldOld(FieldBase):
|
class FieldOld(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
birthday = parse_dt(profile[self.key])
|
birthday = parse_dt(profile[self.key])
|
||||||
return int((datetime.now() - birthday).days / 365.25)
|
return int((datetime.now() - birthday).days / 365.25)
|
||||||
|
|
||||||
|
|
||||||
class FieldSplit(FieldBase):
|
class FieldSplit(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
return [html2text(s).strip() for s in profile[self.key].split(self.key2) if len(s.strip()) > 0]
|
return [html2text(s).strip() for s in profile[self.key].split(self.key2) if len(s.strip()) > 0]
|
||||||
|
|
||||||
|
|
||||||
class FieldBMI(FieldBase):
|
class FieldBMI(FieldBase):
|
||||||
def __init__(self, key, key2, fat=False):
|
def __init__(self, key, key2, fat=False):
|
||||||
FieldBase.__init__(self, key, key2)
|
FieldBase.__init__(self, key, key2)
|
||||||
|
|
@ -100,7 +111,7 @@ class FieldBMI(FieldBase):
|
||||||
if height == 0 or weight == 0:
|
if height == 0 or weight == 0:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
bmi = (weight/float(pow(height/100.0, 2)))
|
bmi = (weight / float(pow(height / 100.0, 2)))
|
||||||
if not self.fat:
|
if not self.fat:
|
||||||
return bmi
|
return bmi
|
||||||
elif bmi < 15.5:
|
elif bmi < 15.5:
|
||||||
|
|
@ -114,6 +125,7 @@ class FieldBMI(FieldBase):
|
||||||
else:
|
else:
|
||||||
return 'obese'
|
return 'obese'
|
||||||
|
|
||||||
|
|
||||||
class FieldFlags(FieldBase):
|
class FieldFlags(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
i = int(profile[self.key])
|
i = int(profile[self.key])
|
||||||
|
|
@ -123,6 +135,7 @@ class FieldFlags(FieldBase):
|
||||||
labels.append(html2text(d['label']).strip())
|
labels.append(html2text(d['label']).strip())
|
||||||
return labels
|
return labels
|
||||||
|
|
||||||
|
|
||||||
class FieldList(FieldBase):
|
class FieldList(FieldBase):
|
||||||
def get_value(self, profile, consts):
|
def get_value(self, profile, consts):
|
||||||
i = int(profile[self.key])
|
i = int(profile[self.key])
|
||||||
|
|
@ -131,6 +144,7 @@ class FieldList(FieldBase):
|
||||||
return html2text(d['label']).strip()
|
return html2text(d['label']).strip()
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class Contact(_Contact):
|
class Contact(_Contact):
|
||||||
TABLE = OrderedDict((
|
TABLE = OrderedDict((
|
||||||
('_info', OrderedDict((
|
('_info', OrderedDict((
|
||||||
|
|
@ -247,9 +261,9 @@ class Contact(_Contact):
|
||||||
if node.flags & node.SECTION:
|
if node.flags & node.SECTION:
|
||||||
result += u'\t' * level + node.label + '\n'
|
result += u'\t' * level + node.label + '\n'
|
||||||
for sub in node.value.itervalues():
|
for sub in node.value.itervalues():
|
||||||
result += print_node(sub, level+1)
|
result += print_node(sub, level + 1)
|
||||||
else:
|
else:
|
||||||
if isinstance(node.value, (tuple,list)):
|
if isinstance(node.value, (tuple, list)):
|
||||||
value = ', '.join(unicode(v) for v in node.value)
|
value = ', '.join(unicode(v) for v in node.value)
|
||||||
elif isinstance(node.value, float):
|
elif isinstance(node.value, float):
|
||||||
value = '%.2f' % node.value
|
value = '%.2f' % node.value
|
||||||
|
|
|
||||||
|
|
@ -124,9 +124,9 @@ class PriorityConnection(Optimization):
|
||||||
browser = AuMBrowser('%s@%s' % (name, self.config['domain']), proxy=self.browser.proxy)
|
browser = AuMBrowser('%s@%s' % (name, self.config['domain']), proxy=self.browser.proxy)
|
||||||
try:
|
try:
|
||||||
browser.register(password= password,
|
browser.register(password= password,
|
||||||
sex= 1, #slut
|
sex= 1, # slut
|
||||||
birthday_d= random.randint(1,28),
|
birthday_d= random.randint(1, 28),
|
||||||
birthday_m= random.randint(1,12),
|
birthday_m= random.randint(1, 12),
|
||||||
birthday_y= random.randint(1975, 1990),
|
birthday_y= random.randint(1975, 1990),
|
||||||
zipcode= 75001,
|
zipcode= 75001,
|
||||||
country= 'fr',
|
country= 'fr',
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class ProfilesWalker(Optimization):
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.walk_cron = self.sched.repeat(60, self.enqueue_profiles)
|
self.walk_cron = self.sched.repeat(60, self.enqueue_profiles)
|
||||||
self.view_cron = self.sched.schedule(randint(10,40), self.view_profile)
|
self.view_cron = self.sched.schedule(randint(10, 40), self.view_profile)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
|
@ -77,7 +77,7 @@ class ProfilesWalker(Optimization):
|
||||||
try:
|
try:
|
||||||
id = self.profiles_queue.pop()
|
id = self.profiles_queue.pop()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return # empty queue
|
return # empty queue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with self.browser:
|
with self.browser:
|
||||||
|
|
@ -101,4 +101,4 @@ class ProfilesWalker(Optimization):
|
||||||
print e
|
print e
|
||||||
finally:
|
finally:
|
||||||
if self.view_cron is not None:
|
if self.view_cron is not None:
|
||||||
self.view_cron = self.sched.schedule(randint(10,40), self.view_profile)
|
self.view_cron = self.sched.schedule(randint(10, 40), self.view_profile)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ from weboob.tools.test import BackendTest
|
||||||
from weboob.tools.browser import BrowserUnavailable
|
from weboob.tools.browser import BrowserUnavailable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['AuMTest']
|
__all__ = ['AuMTest']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicRea
|
||||||
|
|
||||||
__all__ = ['BatotoBackend']
|
__all__ = ['BatotoBackend']
|
||||||
|
|
||||||
|
|
||||||
class BatotoBackend(GenericComicReaderBackend):
|
class BatotoBackend(GenericComicReaderBackend):
|
||||||
NAME = 'batoto'
|
NAME = 'batoto'
|
||||||
DESCRIPTION = 'Batoto manga reading website'
|
DESCRIPTION = 'Batoto manga reading website'
|
||||||
|
|
@ -31,4 +32,4 @@ class BatotoBackend(GenericComicReaderBackend):
|
||||||
ID_REGEXP = r'[^/]+/[^/]+'
|
ID_REGEXP = r'[^/]+/[^/]+'
|
||||||
URL_REGEXP = r'.+batoto.(?:com|net)/read/_/(%s).+' % ID_REGEXP
|
URL_REGEXP = r'.+batoto.(?:com|net)/read/_/(%s).+' % ID_REGEXP
|
||||||
ID_TO_URL = 'http://www.batoto.net/read/_/%s'
|
ID_TO_URL = 'http://www.batoto.net/read/_/%s'
|
||||||
PAGES = { URL_REGEXP: DisplayPage }
|
PAGES = {URL_REGEXP: DisplayPage}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
||||||
|
|
||||||
|
|
||||||
class BatotoTest(GenericComicReaderTest):
|
class BatotoTest(GenericComicReaderTest):
|
||||||
BACKEND = 'batoto'
|
BACKEND = 'batoto'
|
||||||
|
|
||||||
def test_download(self):
|
def test_download(self):
|
||||||
return self._test_download('26287/yurumates_ch4_by_primitive-scans')
|
return self._test_download('26287/yurumates_ch4_by_primitive-scans')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,4 +70,3 @@ class BoursoramaBackend(BaseBackend, ICapBank):
|
||||||
with self.browser:
|
with self.browser:
|
||||||
for coming in self.browser.get_coming_operations(account):
|
for coming in self.browser.get_coming_operations(account):
|
||||||
yield coming
|
yield coming
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ __all__ = ['Boursorama']
|
||||||
class Boursorama(BaseBrowser):
|
class Boursorama(BaseBrowser):
|
||||||
DOMAIN = 'www.boursorama.com'
|
DOMAIN = 'www.boursorama.com'
|
||||||
PROTOCOL = 'https'
|
PROTOCOL = 'https'
|
||||||
ENCODING = None # refer to the HTML encoding
|
ENCODING = None # refer to the HTML encoding
|
||||||
PAGES = {
|
PAGES = {
|
||||||
'.*connexion.phtml.*': LoginPage,
|
'.*connexion.phtml.*': LoginPage,
|
||||||
'.*/comptes/synthese.phtml': AccountsList,
|
'.*/comptes/synthese.phtml': AccountsList,
|
||||||
|
|
@ -84,11 +84,11 @@ class Boursorama(BaseBrowser):
|
||||||
self.location(account._link_id)
|
self.location(account._link_id)
|
||||||
operations = self.page.get_operations()
|
operations = self.page.get_operations()
|
||||||
# load last month as well
|
# load last month as well
|
||||||
target = date.today() - relativedelta( months = 1 )
|
target = date.today() - relativedelta(months=1)
|
||||||
self.location(account._link_id + ("&month=%d&year=%d" % (target.month, target.year)))
|
self.location(account._link_id + ("&month=%d&year=%d" % (target.month, target.year)))
|
||||||
operations += self.page.get_operations()
|
operations += self.page.get_operations()
|
||||||
# and the month before, just in case you're greedy
|
# and the month before, just in case you're greedy
|
||||||
target = date.today() - relativedelta( months = 2 )
|
target = date.today() - relativedelta(months=2)
|
||||||
self.location(account._link_id + ("&month=%d&year=%d" % (target.month, target.year)))
|
self.location(account._link_id + ("&month=%d&year=%d" % (target.month, target.year)))
|
||||||
operations += self.page.get_operations()
|
operations += self.page.get_operations()
|
||||||
for index, op in enumerate(operations):
|
for index, op in enumerate(operations):
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ from .account_history import AccountHistory
|
||||||
from .accounts_list import AccountsList
|
from .accounts_list import AccountsList
|
||||||
from .login import LoginPage
|
from .login import LoginPage
|
||||||
|
|
||||||
class AccountPrelevement(AccountsList): pass
|
class AccountPrelevement(AccountsList):
|
||||||
|
pass
|
||||||
|
|
||||||
__all__ = ['LoginPage',
|
__all__ = ['LoginPage',
|
||||||
'AccountsList',
|
'AccountsList',
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
from weboob.capabilities.bank import Account
|
from weboob.capabilities.bank import Account
|
||||||
from weboob.tools.browser import BasePage
|
from weboob.tools.browser import BasePage
|
||||||
|
|
||||||
class AccountsList(BasePage):
|
|
||||||
|
|
||||||
|
class AccountsList(BasePage):
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -34,34 +34,34 @@ class AccountsList(BasePage):
|
||||||
for tr in div.getiterator('tr'):
|
for tr in div.getiterator('tr'):
|
||||||
account = Account()
|
account = Account()
|
||||||
for td in tr.getiterator('td'):
|
for td in tr.getiterator('td'):
|
||||||
if td.attrib.get('class', '') == 'account-cb':
|
if td.attrib.get('class', '') == 'account-cb':
|
||||||
break
|
break
|
||||||
|
|
||||||
elif td.attrib.get('class', '') == 'account-name':
|
elif td.attrib.get('class', '') == 'account-name':
|
||||||
a = td.find('a')
|
a = td.find('a')
|
||||||
account.label = a.text
|
account.label = a.text
|
||||||
account._link_id = a.get('href', '')
|
account._link_id = a.get('href', '')
|
||||||
|
|
||||||
elif td.attrib.get('class', '') == 'account-number':
|
elif td.attrib.get('class', '') == 'account-number':
|
||||||
id = td.text
|
id = td.text
|
||||||
id = id.strip(u' \n\t')
|
id = id.strip(u' \n\t')
|
||||||
account.id = id
|
account.id = id
|
||||||
|
|
||||||
elif td.attrib.get('class', '') == 'account-total':
|
elif td.attrib.get('class', '') == 'account-total':
|
||||||
span = td.find('span')
|
span = td.find('span')
|
||||||
if span == None:
|
if span == None:
|
||||||
balance = td.text
|
balance = td.text
|
||||||
else:
|
else:
|
||||||
balance = span.text
|
balance = span.text
|
||||||
balance = balance.strip(u' \n\t€+').replace(',','.').replace(' ','')
|
balance = balance.strip(u' \n\t€+').replace(',', '.').replace(' ', '')
|
||||||
if balance != "":
|
if balance != "":
|
||||||
account.balance = float(balance)
|
account.balance = float(balance)
|
||||||
else:
|
else:
|
||||||
account.balance = 0.0
|
account.balance = 0.0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# because of some weird useless <tr>
|
# because of some weird useless <tr>
|
||||||
if account.id != 0:
|
if account.id != 0:
|
||||||
l.append(account)
|
l.append(account)
|
||||||
|
|
||||||
return l
|
return l
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ __all__ = ['LoginPage']
|
||||||
|
|
||||||
class LoginPage(BasePage):
|
class LoginPage(BasePage):
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
pass
|
pass
|
||||||
# for td in self.document.getroot().cssselect('td.LibelleErreur'):
|
# for td in self.document.getroot().cssselect('td.LibelleErreur'):
|
||||||
# if td.text is None:
|
# if td.text is None:
|
||||||
# continue
|
# continue
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ __all__ = ['BPBrowser']
|
||||||
class BPBrowser(BaseBrowser):
|
class BPBrowser(BaseBrowser):
|
||||||
DOMAIN = 'voscomptesenligne.labanquepostale.fr'
|
DOMAIN = 'voscomptesenligne.labanquepostale.fr'
|
||||||
PROTOCOL = 'https'
|
PROTOCOL = 'https'
|
||||||
ENCODING = None # refer to the HTML encoding
|
ENCODING = None # refer to the HTML encoding
|
||||||
PAGES = {r'.*wsost/OstBrokerWeb/loginform.*' : LoginPage,
|
PAGES = {r'.*wsost/OstBrokerWeb/loginform.*' : LoginPage,
|
||||||
r'.*authentification/repositionnerCheminCourant-identif.ea' : repositionnerCheminCourant,
|
r'.*authentification/repositionnerCheminCourant-identif.ea' : repositionnerCheminCourant,
|
||||||
r'.*authentification/initialiser-identif.ea' : Initident,
|
r'.*authentification/initialiser-identif.ea' : Initident,
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class AccountHistory(BasePage):
|
||||||
for t in tmp:
|
for t in tmp:
|
||||||
if r.search(t.text):
|
if r.search(t.text):
|
||||||
amount = t.text
|
amount = t.text
|
||||||
amount = ''.join( amount.replace('.', '').replace(',', '.').split() )
|
amount = ''.join(amount.replace('.', '').replace(',', '.').split())
|
||||||
if amount[0] == "-":
|
if amount[0] == "-":
|
||||||
operation.amount = -float(amount[1:])
|
operation.amount = -float(amount[1:])
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ __all__ = ['CanalplusVideo']
|
||||||
|
|
||||||
class CanalplusVideo(BaseVideo):
|
class CanalplusVideo(BaseVideo):
|
||||||
swf_player = False
|
swf_player = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def id2url(cls, _id):
|
def id2url(cls, _id):
|
||||||
return 'http://service.canal-plus.com/video/rest/getVideosLiees/cplus/%s' % _id
|
return 'http://service.canal-plus.com/video/rest/getVideosLiees/cplus/%s' % _id
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,10 @@ from lxml import etree
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['CmbBackend']
|
__all__ = ['CmbBackend']
|
||||||
|
|
||||||
|
|
||||||
class CmbBackend(BaseBackend, ICapBank):
|
class CmbBackend(BaseBackend, ICapBank):
|
||||||
NAME = 'cmb'
|
NAME = 'cmb'
|
||||||
MAINTAINER = 'Johann Broudin'
|
MAINTAINER = 'Johann Broudin'
|
||||||
|
|
@ -83,7 +85,6 @@ class CmbBackend(BaseBackend, ICapBank):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
cookie = None
|
cookie = None
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent':
|
'User-Agent':
|
||||||
|
|
@ -167,13 +168,13 @@ class CmbBackend(BaseBackend, ICapBank):
|
||||||
|
|
||||||
|
|
||||||
balance = td[1].text
|
balance = td[1].text
|
||||||
balance = balance.replace(',','.').replace(u"\xa0",'')
|
balance = balance.replace(',', '.').replace(u"\xa0", '')
|
||||||
account.balance = float(balance)
|
account.balance = float(balance)
|
||||||
|
|
||||||
span = td[3].xpath('a/span')
|
span = td[3].xpath('a/span')
|
||||||
if len(span):
|
if len(span):
|
||||||
coming = span[0].text.replace(' ','').replace(',','.')
|
coming = span[0].text.replace(' ', '').replace(',', '.')
|
||||||
coming = coming.replace(u"\xa0",'')
|
coming = coming.replace(u"\xa0", '')
|
||||||
account.coming = float(coming)
|
account.coming = float(coming)
|
||||||
else:
|
else:
|
||||||
account.coming = NotAvailable
|
account.coming = NotAvailable
|
||||||
|
|
@ -248,7 +249,7 @@ class CmbBackend(BaseBackend, ICapBank):
|
||||||
operation.date = date(*reversed([int(x) for x in d]))
|
operation.date = date(*reversed([int(x) for x in d]))
|
||||||
|
|
||||||
div = td[2].xpath('div')
|
div = td[2].xpath('div')
|
||||||
label = div[0].xpath('a')[0].text.replace('\n','')
|
label = div[0].xpath('a')[0].text.replace('\n', '')
|
||||||
operation.raw = unicode(' '.join(label.split()))
|
operation.raw = unicode(' '.join(label.split()))
|
||||||
for pattern, _type, _label in self.LABEL_PATTERNS:
|
for pattern, _type, _label in self.LABEL_PATTERNS:
|
||||||
mm = pattern.match(operation.raw)
|
mm = pattern.match(operation.raw)
|
||||||
|
|
@ -260,12 +261,11 @@ class CmbBackend(BaseBackend, ICapBank):
|
||||||
amount = td[3].text
|
amount = td[3].text
|
||||||
if amount.count(',') != 1:
|
if amount.count(',') != 1:
|
||||||
amount = td[4].text
|
amount = td[4].text
|
||||||
amount = amount.replace(',','.').replace(u'\xa0','')
|
amount = amount.replace(',', '.').replace(u'\xa0', '')
|
||||||
operation.amount = float(amount)
|
operation.amount = float(amount)
|
||||||
else:
|
else:
|
||||||
amount = amount.replace(',','.').replace(u'\xa0','')
|
amount = amount.replace(',', '.').replace(u'\xa0', '')
|
||||||
operation.amount = - float(amount)
|
operation.amount = - float(amount)
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
yield operation
|
yield operation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ from weboob.capabilities.bank import Account
|
||||||
from .base import CragrBasePage
|
from .base import CragrBasePage
|
||||||
from weboob.capabilities.bank import Transaction
|
from weboob.capabilities.bank import Transaction
|
||||||
|
|
||||||
|
|
||||||
def clean_amount(amount):
|
def clean_amount(amount):
|
||||||
"""
|
"""
|
||||||
Removes weird characters and converts to a float
|
Removes weird characters and converts to a float
|
||||||
|
|
@ -34,6 +35,7 @@ def clean_amount(amount):
|
||||||
matches = re.findall('^(-?[0-9]+\.[0-9]{2}).*$', data)
|
matches = re.findall('^(-?[0-9]+\.[0-9]{2}).*$', data)
|
||||||
return float(matches[0]) if (matches) else 0.0
|
return float(matches[0]) if (matches) else 0.0
|
||||||
|
|
||||||
|
|
||||||
class AccountsList(CragrBasePage):
|
class AccountsList(CragrBasePage):
|
||||||
|
|
||||||
def get_list(self):
|
def get_list(self):
|
||||||
|
|
@ -109,7 +111,7 @@ class AccountsList(CragrBasePage):
|
||||||
select_name is the name of the select field to analyze
|
select_name is the name of the select field to analyze
|
||||||
"""
|
"""
|
||||||
if not self.is_transfer_page():
|
if not self.is_transfer_page():
|
||||||
return False
|
return False
|
||||||
source_accounts = {}
|
source_accounts = {}
|
||||||
source_account_options = self.document.xpath('/html/body//form//select[@name="%s"]/option' % select_name)
|
source_account_options = self.document.xpath('/html/body//form//select[@name="%s"]/option' % select_name)
|
||||||
for option in source_account_options:
|
for option in source_account_options:
|
||||||
|
|
@ -212,7 +214,7 @@ class AccountsList(CragrBasePage):
|
||||||
year = today.year
|
year = today.year
|
||||||
return date(year, month, day)
|
return date(year, month, day)
|
||||||
|
|
||||||
def get_history(self, start_index = 0, start_offset = 0):
|
def get_history(self, start_index=0, start_offset=0):
|
||||||
"""
|
"""
|
||||||
Returns the history of a specific account. Note that this function
|
Returns the history of a specific account. Note that this function
|
||||||
expects the current page to be the one dedicated to this history.
|
expects the current page to be the one dedicated to this history.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from .pages import LoginPage, LoginErrorPage, AccountsPage, UserSpacePage, Opera
|
||||||
|
|
||||||
__all__ = ['CreditMutuelBrowser']
|
__all__ = ['CreditMutuelBrowser']
|
||||||
|
|
||||||
|
|
||||||
# Browser
|
# Browser
|
||||||
class CreditMutuelBrowser(BaseBrowser):
|
class CreditMutuelBrowser(BaseBrowser):
|
||||||
PROTOCOL = 'https'
|
PROTOCOL = 'https'
|
||||||
|
|
@ -36,11 +37,11 @@ class CreditMutuelBrowser(BaseBrowser):
|
||||||
'https://www.creditmutuel.fr/groupe/fr/identification/default.cgi': LoginErrorPage,
|
'https://www.creditmutuel.fr/groupe/fr/identification/default.cgi': LoginErrorPage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/situation_financiere.cgi': AccountsPage,
|
'https://www.creditmutuel.fr/.*/fr/banque/situation_financiere.cgi': AccountsPage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/espace_personnel.aspx': UserSpacePage,
|
'https://www.creditmutuel.fr/.*/fr/banque/espace_personnel.aspx': UserSpacePage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/mouvements.cgi.*' : OperationsPage,
|
'https://www.creditmutuel.fr/.*/fr/banque/mouvements.cgi.*': OperationsPage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/nr/nr_devbooster.aspx.*' : OperationsPage,
|
'https://www.creditmutuel.fr/.*/fr/banque/nr/nr_devbooster.aspx.*': OperationsPage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/operations_carte\.cgi.*' : OperationsPage,
|
'https://www.creditmutuel.fr/.*/fr/banque/operations_carte\.cgi.*': OperationsPage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/BAD.*' : InfoPage,
|
'https://www.creditmutuel.fr/.*/fr/banque/BAD.*': InfoPage,
|
||||||
'https://www.creditmutuel.fr/.*/fr/banque/.*Vir.*' : TransfertPage
|
'https://www.creditmutuel.fr/.*/fr/banque/.*Vir.*': TransfertPage
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
@ -61,17 +62,17 @@ class CreditMutuelBrowser(BaseBrowser):
|
||||||
if not self.is_on_page(LoginPage):
|
if not self.is_on_page(LoginPage):
|
||||||
self.location('https://www.creditmutuel.fr/', no_login=True)
|
self.location('https://www.creditmutuel.fr/', no_login=True)
|
||||||
|
|
||||||
self.page.login( self.username, self.password)
|
self.page.login(self.username, self.password)
|
||||||
|
|
||||||
if not self.is_logged() or self.is_on_page(LoginErrorPage):
|
if not self.is_logged() or self.is_on_page(LoginErrorPage):
|
||||||
raise BrowserIncorrectPassword()
|
raise BrowserIncorrectPassword()
|
||||||
|
|
||||||
self.SUB_BANKS = ['cmdv','cmcee','cmse', 'cmidf', 'cmsmb', 'cmma', 'cmmabn', 'cmc', 'cmlaco', 'cmnormandie', 'cmm']
|
self.SUB_BANKS = ['cmdv', 'cmcee', 'cmse', 'cmidf', 'cmsmb', 'cmma', 'cmmabn', 'cmc', 'cmlaco', 'cmnormandie', 'cmm']
|
||||||
self.getCurrentSubBank()
|
self.getCurrentSubBank()
|
||||||
|
|
||||||
def get_accounts_list(self):
|
def get_accounts_list(self):
|
||||||
if not self.is_on_page(AccountsPage):
|
if not self.is_on_page(AccountsPage):
|
||||||
self.location('https://www.creditmutuel.fr/%s/fr/banque/situation_financiere.cgi'%self.currentSubBank)
|
self.location('https://www.creditmutuel.fr/%s/fr/banque/situation_financiere.cgi' % self.currentSubBank)
|
||||||
return self.page.get_list()
|
return self.page.get_list()
|
||||||
|
|
||||||
def get_account(self, id):
|
def get_account(self, id):
|
||||||
|
|
@ -121,13 +122,13 @@ class CreditMutuelBrowser(BaseBrowser):
|
||||||
def transfer(self, account, to, amount, reason=None):
|
def transfer(self, account, to, amount, reason=None):
|
||||||
# access the transfer page
|
# access the transfer page
|
||||||
transfert_url = 'WI_VPLV_VirUniSaiCpt.asp?RAZ=ALL&Cat=6&PERM=N&CHX=A'
|
transfert_url = 'WI_VPLV_VirUniSaiCpt.asp?RAZ=ALL&Cat=6&PERM=N&CHX=A'
|
||||||
self.location('https://%s/%s/fr/banque/%s'%(self.DOMAIN, self.currentSubBank, transfert_url))
|
self.location('https://%s/%s/fr/banque/%s' % (self.DOMAIN, self.currentSubBank, transfert_url))
|
||||||
|
|
||||||
# fill the form
|
# fill the form
|
||||||
self.select_form(name='FormVirUniSaiCpt')
|
self.select_form(name='FormVirUniSaiCpt')
|
||||||
self['IDB'] = [account[-1]]
|
self['IDB'] = [account[-1]]
|
||||||
self['ICR'] = [to[-1]]
|
self['ICR'] = [to[-1]]
|
||||||
self['MTTVIR'] = '%s' % str(amount).replace('.',',')
|
self['MTTVIR'] = '%s' % str(amount).replace('.', ',')
|
||||||
if reason != None:
|
if reason != None:
|
||||||
self['LIBDBT'] = reason
|
self['LIBDBT'] = reason
|
||||||
self['LIBCRT'] = reason
|
self['LIBCRT'] = reason
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ from ..tools import url2id
|
||||||
from .index import DLFPPage
|
from .index import DLFPPage
|
||||||
|
|
||||||
class RSSComment(DLFPPage):
|
class RSSComment(DLFPPage):
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Content(object):
|
class Content(object):
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicRea
|
||||||
|
|
||||||
__all__ = ['EatmangaBackend']
|
__all__ = ['EatmangaBackend']
|
||||||
|
|
||||||
|
|
||||||
class EatmangaBackend(GenericComicReaderBackend):
|
class EatmangaBackend(GenericComicReaderBackend):
|
||||||
NAME = 'eatmanga'
|
NAME = 'eatmanga'
|
||||||
DESCRIPTION = 'EatManga manga reading website'
|
DESCRIPTION = 'EatManga manga reading website'
|
||||||
|
|
@ -31,4 +32,4 @@ class EatmangaBackend(GenericComicReaderBackend):
|
||||||
ID_REGEXP = r'[^/]+/[^/]+'
|
ID_REGEXP = r'[^/]+/[^/]+'
|
||||||
URL_REGEXP = r'.+eatmanga.com/(?:index.php/)?Manga-Scan/(%s).+' % ID_REGEXP
|
URL_REGEXP = r'.+eatmanga.com/(?:index.php/)?Manga-Scan/(%s).+' % ID_REGEXP
|
||||||
ID_TO_URL = 'http://www.eatmanga.com/index.php/Manga-Scan/%s'
|
ID_TO_URL = 'http://www.eatmanga.com/index.php/Manga-Scan/%s'
|
||||||
PAGES = { URL_REGEXP: DisplayPage }
|
PAGES = {URL_REGEXP: DisplayPage}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
||||||
|
|
||||||
|
|
||||||
class EatmangaTest(GenericComicReaderTest):
|
class EatmangaTest(GenericComicReaderTest):
|
||||||
BACKEND = 'eatmanga'
|
BACKEND = 'eatmanga'
|
||||||
|
|
||||||
def test_download(self):
|
def test_download(self):
|
||||||
return self._test_download('Glass-Mask/Glass-Mask-Vol-031')
|
return self._test_download('Glass-Mask/Glass-Mask-Vol-031')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,4 +96,4 @@ class EHentaiBackend(BaseBackend, ICapGallery):
|
||||||
|
|
||||||
OBJECTS = {
|
OBJECTS = {
|
||||||
EHentaiGallery: fill_gallery,
|
EHentaiGallery: fill_gallery,
|
||||||
EHentaiImage: fill_image }
|
EHentaiImage: fill_image}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class EHentaiBrowser(BaseBrowser):
|
||||||
assert self.is_on_page(GalleryPage)
|
assert self.is_on_page(GalleryPage)
|
||||||
i = 0
|
i = 0
|
||||||
while True:
|
while True:
|
||||||
n = self.page._next_page_link();
|
n = self.page._next_page_link()
|
||||||
|
|
||||||
for img in self.page.image_pages():
|
for img in self.page.image_pages():
|
||||||
yield EHentaiImage(img)
|
yield EHentaiImage(img)
|
||||||
|
|
@ -104,4 +104,3 @@ class EHentaiBrowser(BaseBrowser):
|
||||||
|
|
||||||
# necessary in order to reach the fjords
|
# necessary in order to reach the fjords
|
||||||
self.home()
|
self.home()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from .gallery import EHentaiGallery
|
||||||
|
|
||||||
__all__ = ['GalleryPage', 'ImagePage', 'IndexPage', 'HomePage', 'LoginPage']
|
__all__ = ['GalleryPage', 'ImagePage', 'IndexPage', 'HomePage', 'LoginPage']
|
||||||
|
|
||||||
|
|
||||||
class LoginPage(BasePage):
|
class LoginPage(BasePage):
|
||||||
def is_logged(self):
|
def is_logged(self):
|
||||||
success_p = self.document.xpath(
|
success_p = self.document.xpath(
|
||||||
|
|
@ -38,9 +39,11 @@ class LoginPage(BasePage):
|
||||||
print 'not logged on'
|
print 'not logged on'
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class HomePage(BasePage):
|
class HomePage(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IndexPage(BasePage):
|
class IndexPage(BasePage):
|
||||||
def iter_galleries(self):
|
def iter_galleries(self):
|
||||||
lines = self.document.xpath('//table[@class="itg"]//tr[@class="gtr0" or @class="gtr1"]')
|
lines = self.document.xpath('//table[@class="itg"]//tr[@class="gtr0" or @class="gtr1"]')
|
||||||
|
|
@ -50,6 +53,7 @@ class IndexPage(BasePage):
|
||||||
title = a.text.strip()
|
title = a.text.strip()
|
||||||
yield EHentaiGallery(re.search('(?<=/g/)\d+/[\dabcdef]+', url).group(0), title=title)
|
yield EHentaiGallery(re.search('(?<=/g/)\d+/[\dabcdef]+', url).group(0), title=title)
|
||||||
|
|
||||||
|
|
||||||
class GalleryPage(BasePage):
|
class GalleryPage(BasePage):
|
||||||
def image_pages(self):
|
def image_pages(self):
|
||||||
return self.document.xpath('//div[@class="gdtm"]//a/attribute::href')
|
return self.document.xpath('//div[@class="gdtm"]//a/attribute::href')
|
||||||
|
|
@ -102,7 +106,7 @@ class GalleryPage(BasePage):
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ImagePage(BasePage):
|
class ImagePage(BasePage):
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
return self.document.xpath('//div[@class="sni"]/a/img/attribute::src')[0]
|
return self.document.xpath('//div[@class="sni"]/a/img/attribute::src')[0]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
from weboob.tools.test import BackendTest
|
from weboob.tools.test import BackendTest
|
||||||
|
|
||||||
|
|
||||||
class EHentaiTest(BackendTest):
|
class EHentaiTest(BackendTest):
|
||||||
BACKEND = 'ehentai'
|
BACKEND = 'ehentai'
|
||||||
|
|
||||||
|
|
@ -35,4 +36,3 @@ class EHentaiTest(BackendTest):
|
||||||
self.backend.fillobj(img, ('url',))
|
self.backend.fillobj(img, ('url',))
|
||||||
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for first image in gallery "%s" not found: %s' % (v.id, img.url))
|
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for first image in gallery "%s" not found: %s' % (v.id, img.url))
|
||||||
self.backend.browser.openurl(img.url)
|
self.backend.browser.openurl(img.url)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class FourChanBackend(BaseBackend, ICapMessages):
|
||||||
thread = Thread(id)
|
thread = Thread(id)
|
||||||
thread.title = _thread.filename
|
thread.title = _thread.filename
|
||||||
thread.root = Message(thread=thread,
|
thread.root = Message(thread=thread,
|
||||||
id=0, # root message
|
id=0, # root message
|
||||||
title=_thread.filename,
|
title=_thread.filename,
|
||||||
sender=_thread.author,
|
sender=_thread.author,
|
||||||
receivers=None,
|
receivers=None,
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,11 @@ __all__ = ['ValidationPage', 'HomePage', 'HistoryPage', 'StoryPage']
|
||||||
class ValidationPage(BasePage):
|
class ValidationPage(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HomePage(BasePage):
|
class HomePage(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Author(object):
|
class Author(object):
|
||||||
(UNKNOWN,
|
(UNKNOWN,
|
||||||
MALE,
|
MALE,
|
||||||
|
|
@ -45,6 +47,7 @@ class Author(object):
|
||||||
self.email = None
|
self.email = None
|
||||||
self.description = None
|
self.description = None
|
||||||
|
|
||||||
|
|
||||||
class Story(object):
|
class Story(object):
|
||||||
def __init__(self, id):
|
def __init__(self, id):
|
||||||
self.id = id
|
self.id = id
|
||||||
|
|
@ -54,6 +57,7 @@ class Story(object):
|
||||||
self.author = None
|
self.author = None
|
||||||
self.body = None
|
self.body = None
|
||||||
|
|
||||||
|
|
||||||
class HistoryPage(BasePage):
|
class HistoryPage(BasePage):
|
||||||
def get_numerous(self):
|
def get_numerous(self):
|
||||||
td = self.parser.select(self.document.getroot(), 'td.t0', 1)
|
td = self.parser.select(self.document.getroot(), 'td.t0', 1)
|
||||||
|
|
@ -89,6 +93,7 @@ class HistoryPage(BasePage):
|
||||||
yield story
|
yield story
|
||||||
story = None
|
story = None
|
||||||
|
|
||||||
|
|
||||||
class StoryPage(BasePage):
|
class StoryPage(BasePage):
|
||||||
def get_story(self):
|
def get_story(self):
|
||||||
p_tags = self.document.getroot().xpath('//body/p')
|
p_tags = self.document.getroot().xpath('//body/p')
|
||||||
|
|
@ -179,4 +184,3 @@ class AuthorPage(BasePage):
|
||||||
if author.description.startswith(u'0 récit '):
|
if author.description.startswith(u'0 récit '):
|
||||||
self.logger.warning('This author does not have published any story.')
|
self.logger.warning('This author does not have published any story.')
|
||||||
return author
|
return author
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,24 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
def id2url(_id):
|
def id2url(_id):
|
||||||
"return an url from an id"
|
"return an url from an id"
|
||||||
regexp2 = re.compile("(\w+).([0-9]+).(.*$)")
|
regexp2 = re.compile("(\w+).([0-9]+).(.*$)")
|
||||||
match = regexp2.match(_id)
|
match = regexp2.match(_id)
|
||||||
if match:
|
if match:
|
||||||
return 'http://www.20minutes.fr/%s/%s/%s' % ( match.group(1),
|
return 'http://www.20minutes.fr/%s/%s/%s' % (match.group(1),
|
||||||
match.group(2),
|
match.group(2),
|
||||||
match.group(3))
|
match.group(3))
|
||||||
else:
|
else:
|
||||||
raise ValueError("id doesn't match")
|
raise ValueError("id doesn't match")
|
||||||
|
|
||||||
|
|
||||||
def url2id(url):
|
def url2id(url):
|
||||||
"return an id from an url"
|
"return an id from an url"
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
def rssid(entry):
|
def rssid(entry):
|
||||||
return url2id(entry.id)
|
return url2id(entry.id)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ from weboob.tools.browser import BaseBrowser, BasePage
|
||||||
|
|
||||||
__all__ = ['IzneoBackend']
|
__all__ = ['IzneoBackend']
|
||||||
|
|
||||||
|
|
||||||
class ReaderV2(BasePage):
|
class ReaderV2(BasePage):
|
||||||
def get_ean(self):
|
def get_ean(self):
|
||||||
return self.document.xpath("//div[@id='viewer']/attribute::rel")[0]
|
return self.document.xpath("//div[@id='viewer']/attribute::rel")[0]
|
||||||
|
|
@ -43,14 +44,15 @@ class ReaderV2(BasePage):
|
||||||
% ean))
|
% ean))
|
||||||
|
|
||||||
for page in pages:
|
for page in pages:
|
||||||
width = 1200 # maximum width
|
width = 1200 # maximum width
|
||||||
yield BaseImage(page['page'],
|
yield BaseImage(page['page'],
|
||||||
gallery=gallery,
|
gallery=gallery,
|
||||||
url=("http://www.izneo.com/playerv2/%s/%s/%s/%d/%s" %
|
url=("http://www.izneo.com/playerv2/%s/%s/%s/%d/%s" %
|
||||||
(page['expires'], page['token'], ean, width, page['page'])))
|
(page['expires'], page['token'], ean, width, page['page'])))
|
||||||
|
|
||||||
|
|
||||||
class IzneoBrowser(BaseBrowser):
|
class IzneoBrowser(BaseBrowser):
|
||||||
PAGES = { r'http://.+\.izneo.\w+/readv2-.+': ReaderV2 }
|
PAGES = {r'http://.+\.izneo.\w+/readv2-.+': ReaderV2}
|
||||||
|
|
||||||
def iter_gallery_images(self, gallery):
|
def iter_gallery_images(self, gallery):
|
||||||
self.location(gallery.url)
|
self.location(gallery.url)
|
||||||
|
|
@ -88,7 +90,7 @@ class IzneoBackend(BaseBackend, ICapGallery):
|
||||||
return gallery
|
return gallery
|
||||||
|
|
||||||
def fill_gallery(self, gallery, fields):
|
def fill_gallery(self, gallery, fields):
|
||||||
gallery.title = gallery.id
|
gallery.title = gallery.id
|
||||||
|
|
||||||
def fill_image(self, image, fields):
|
def fill_image(self, image, fields):
|
||||||
with self.browser:
|
with self.browser:
|
||||||
|
|
@ -96,4 +98,4 @@ class IzneoBackend(BaseBackend, ICapGallery):
|
||||||
|
|
||||||
OBJECTS = {
|
OBJECTS = {
|
||||||
BaseGallery: fill_gallery,
|
BaseGallery: fill_gallery,
|
||||||
BaseImage: fill_image }
|
BaseImage: fill_image}
|
||||||
|
|
|
||||||
|
|
@ -67,4 +67,3 @@ class LCLBackend(BaseBackend, ICapBank):
|
||||||
with self.browser:
|
with self.browser:
|
||||||
for history in self.browser.get_history(account):
|
for history in self.browser.get_history(account):
|
||||||
yield history
|
yield history
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,18 @@ import tempfile
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
class LCLVirtKeyboard(MappedVirtKeyboard):
|
class LCLVirtKeyboard(MappedVirtKeyboard):
|
||||||
symbols={'0':'9da2724133f2221482013151735f033c',
|
symbols={'0': '9da2724133f2221482013151735f033c',
|
||||||
'1':'873ab0087447610841ae1332221be37b',
|
'1': '873ab0087447610841ae1332221be37b',
|
||||||
'2':'93ce6c330393ff5980949d7b6c800f77',
|
'2': '93ce6c330393ff5980949d7b6c800f77',
|
||||||
'3':'b2d70c69693784e1bf1f0973d81223c0',
|
'3': 'b2d70c69693784e1bf1f0973d81223c0',
|
||||||
'4':'498c8f5d885611938f94f1c746c32978',
|
'4': '498c8f5d885611938f94f1c746c32978',
|
||||||
'5':'359bcd60a9b8565917a7bf34522052c3',
|
'5': '359bcd60a9b8565917a7bf34522052c3',
|
||||||
'6':'aba912172f21f78cd6da437cfc4cdbd0',
|
'6': 'aba912172f21f78cd6da437cfc4cdbd0',
|
||||||
'7':'f710190d6b947869879ec02d8e851dfa',
|
'7': 'f710190d6b947869879ec02d8e851dfa',
|
||||||
'8':'b42cc25e1539a15f767aa7a641f3bfec',
|
'8': 'b42cc25e1539a15f767aa7a641f3bfec',
|
||||||
'9':'cc60e5894a9d8e12ee0c2c104c1d5490'
|
'9': 'cc60e5894a9d8e12ee0c2c104c1d5490'
|
||||||
}
|
}
|
||||||
|
|
||||||
url="/outil/UAUT/Clavier/creationClavier?random="
|
url="/outil/UAUT/Clavier/creationClavier?random="
|
||||||
|
|
@ -66,9 +67,11 @@ class LCLVirtKeyboard(MappedVirtKeyboard):
|
||||||
code+=self.get_symbol_code(self.symbols[c])
|
code+=self.get_symbol_code(self.symbols[c])
|
||||||
return code
|
return code
|
||||||
|
|
||||||
|
|
||||||
class SkipPage(BasePage):
|
class SkipPage(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LoginPage(BasePage):
|
class LoginPage(BasePage):
|
||||||
def myXOR(self,value,seed):
|
def myXOR(self,value,seed):
|
||||||
s=''
|
s=''
|
||||||
|
|
@ -120,6 +123,7 @@ class LoginPage(BasePage):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class AccountsPage(BasePage):
|
class AccountsPage(BasePage):
|
||||||
def get_list(self):
|
def get_list(self):
|
||||||
l = []
|
l = []
|
||||||
|
|
@ -145,6 +149,7 @@ class AccountsPage(BasePage):
|
||||||
l.append(account)
|
l.append(account)
|
||||||
return l
|
return l
|
||||||
|
|
||||||
|
|
||||||
class AccountHistoryPage(BasePage):
|
class AccountHistoryPage(BasePage):
|
||||||
def get_operations(self,account):
|
def get_operations(self,account):
|
||||||
operations = []
|
operations = []
|
||||||
|
|
@ -194,5 +199,3 @@ class AccountHistoryPage(BasePage):
|
||||||
operation.amount=amount
|
operation.amount=amount
|
||||||
operations.append(operation)
|
operations.append(operation)
|
||||||
return operations
|
return operations
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage, remove_from_selector_list, drop_comments, try_drop_tree, try_remove_from_selector_list
|
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage, remove_from_selector_list, drop_comments, try_drop_tree, try_remove_from_selector_list
|
||||||
|
|
||||||
|
|
||||||
class ArticlePage(GenericNewsPage):
|
class ArticlePage(GenericNewsPage):
|
||||||
"ArticlePage object for inrocks"
|
"ArticlePage object for inrocks"
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
|
|
@ -51,7 +52,6 @@ class ArticlePage(GenericNewsPage):
|
||||||
a.drop_tree()
|
a.drop_tree()
|
||||||
div.drop_tree()
|
div.drop_tree()
|
||||||
|
|
||||||
|
|
||||||
# This part of the article seems manually generated.
|
# This part of the article seems manually generated.
|
||||||
for crappy_title in self.parser.select(element_body, 'p strong'):
|
for crappy_title in self.parser.select(element_body, 'p strong'):
|
||||||
if crappy_title.text == 'LIRE AUSSI :' or crappy_title.text == 'LIRE AUSSI:':
|
if crappy_title.text == 'LIRE AUSSI :' or crappy_title.text == 'LIRE AUSSI:':
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,12 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage
|
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage
|
||||||
|
|
||||||
|
|
||||||
class FlashActuPage(GenericNewsPage):
|
class FlashActuPage(GenericNewsPage):
|
||||||
"ArticlePage object for inrocks"
|
"ArticlePage object for inrocks"
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
self.main_div = self.document.getroot()
|
self.main_div = self.document.getroot()
|
||||||
self.element_title_selector = "h1"
|
self.element_title_selector = "h1"
|
||||||
self.element_author_selector = "div.name>span"
|
self.element_author_selector = "div.name>span"
|
||||||
self.element_body_selector = "h2"
|
self.element_body_selector = "h2"
|
||||||
|
|
||||||
|
|
@ -32,4 +33,3 @@ class FlashActuPage(GenericNewsPage):
|
||||||
element_body = self.get_element_body()
|
element_body = self.get_element_body()
|
||||||
element_body.tag = "div"
|
element_body.tag = "div"
|
||||||
return self.parser.tostring(element_body)
|
return self.parser.tostring(element_body)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,11 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage
|
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage
|
||||||
|
|
||||||
|
|
||||||
class SimplePage(GenericNewsPage):
|
class SimplePage(GenericNewsPage):
|
||||||
"ArticlePage object for minutes20"
|
"ArticlePage object for minutes20"
|
||||||
|
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
self.main_div = self.document.getroot()
|
self.main_div = self.document.getroot()
|
||||||
self.element_author_selector = "div.mna-signature"
|
self.element_author_selector = "div.mna-signature"
|
||||||
self.element_body_selector = "#article"
|
self.element_body_selector = "#article"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,12 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage, try_remove_from_selector_list
|
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage, try_remove_from_selector_list
|
||||||
|
|
||||||
|
|
||||||
class SpecialPage(GenericNewsPage):
|
class SpecialPage(GenericNewsPage):
|
||||||
"ArticlePage object for inrocks"
|
"ArticlePage object for inrocks"
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
self.main_div = self.document.getroot()
|
self.main_div = self.document.getroot()
|
||||||
self.element_title_selector = "h2"
|
self.element_title_selector = "h2"
|
||||||
self.element_author_selector = "div.name>span"
|
self.element_author_selector = "div.name>span"
|
||||||
self.element_body_selector = ".block-text"
|
self.element_body_selector = ".block-text"
|
||||||
|
|
||||||
|
|
@ -32,4 +33,3 @@ class SpecialPage(GenericNewsPage):
|
||||||
try_remove_from_selector_list(self.parser, element_body, ['div'])
|
try_remove_from_selector_list(self.parser, element_body, ['div'])
|
||||||
element_body.tag = "div"
|
element_body.tag = "div"
|
||||||
return self.parser.tostring(element_body)
|
return self.parser.tostring(element_body)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,22 +18,24 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
def id2url(_id):
|
def id2url(_id):
|
||||||
"return an url from an id"
|
"return an url from an id"
|
||||||
regexp2 = re.compile("(\w+).([0-9]+).(.*$)")
|
regexp2 = re.compile("(\w+).([0-9]+).(.*$)")
|
||||||
match = regexp2.match(_id)
|
match = regexp2.match(_id)
|
||||||
if match:
|
if match:
|
||||||
return 'http://www.20minutes.fr/%s/%s/%s' % ( match.group(1),
|
return 'http://www.20minutes.fr/%s/%s/%s' % (match.group(1),
|
||||||
match.group(2),
|
match.group(2),
|
||||||
match.group(3))
|
match.group(3))
|
||||||
else:
|
else:
|
||||||
raise ValueError("id doesn't match")
|
raise ValueError("id doesn't match")
|
||||||
|
|
||||||
|
|
||||||
def url2id(url):
|
def url2id(url):
|
||||||
"return an id from an url"
|
"return an id from an url"
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
def rssid(entry):
|
def rssid(entry):
|
||||||
return url2id(entry.id)
|
return url2id(entry.id)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicRea
|
||||||
|
|
||||||
__all__ = ['MangafoxBackend']
|
__all__ = ['MangafoxBackend']
|
||||||
|
|
||||||
|
|
||||||
class MangafoxBackend(GenericComicReaderBackend):
|
class MangafoxBackend(GenericComicReaderBackend):
|
||||||
NAME = 'mangafox'
|
NAME = 'mangafox'
|
||||||
DESCRIPTION = 'Manga Fox manga reading website'
|
DESCRIPTION = 'Manga Fox manga reading website'
|
||||||
|
|
@ -31,4 +32,4 @@ class MangafoxBackend(GenericComicReaderBackend):
|
||||||
ID_REGEXP = r'[^/]+/[^/]+(?:/[^/]+)?'
|
ID_REGEXP = r'[^/]+/[^/]+(?:/[^/]+)?'
|
||||||
URL_REGEXP = r'.+mangafox.com/manga/(%s).*' % ID_REGEXP
|
URL_REGEXP = r'.+mangafox.com/manga/(%s).*' % ID_REGEXP
|
||||||
ID_TO_URL = 'http://www.mangafox.com/manga/%s'
|
ID_TO_URL = 'http://www.mangafox.com/manga/%s'
|
||||||
PAGES = { r'http://.+\.mangafox.\w+/manga/[^/]+/[^/]+/([^/]+/)?(.+\.html)?': DisplayPage }
|
PAGES = {r'http://.+\.mangafox.\w+/manga/[^/]+/[^/]+/([^/]+/)?(.+\.html)?': DisplayPage}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
||||||
|
|
||||||
|
|
||||||
class MangafoxTest(GenericComicReaderTest):
|
class MangafoxTest(GenericComicReaderTest):
|
||||||
BACKEND = 'mangafox'
|
BACKEND = 'mangafox'
|
||||||
|
|
||||||
def test_download(self):
|
def test_download(self):
|
||||||
return self._test_download('glass_no_kamen/v02/c000')
|
return self._test_download('glass_no_kamen/v02/c000')
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicRea
|
||||||
|
|
||||||
__all__ = ['MangahereBackend']
|
__all__ = ['MangahereBackend']
|
||||||
|
|
||||||
|
|
||||||
class MangahereBackend(GenericComicReaderBackend):
|
class MangahereBackend(GenericComicReaderBackend):
|
||||||
NAME = 'mangahere'
|
NAME = 'mangahere'
|
||||||
DESCRIPTION = 'Manga Here manga reading website'
|
DESCRIPTION = 'Manga Here manga reading website'
|
||||||
|
|
@ -31,4 +32,4 @@ class MangahereBackend(GenericComicReaderBackend):
|
||||||
ID_REGEXP = r'[^/]+/[^/]+/[^/]+'
|
ID_REGEXP = r'[^/]+/[^/]+/[^/]+'
|
||||||
URL_REGEXP = r'.+mangahere.com/manga/(%s).+' % ID_REGEXP
|
URL_REGEXP = r'.+mangahere.com/manga/(%s).+' % ID_REGEXP
|
||||||
ID_TO_URL = 'http://www.mangahere.com/manga/%s'
|
ID_TO_URL = 'http://www.mangahere.com/manga/%s'
|
||||||
PAGES = { URL_REGEXP: DisplayPage }
|
PAGES = {URL_REGEXP: DisplayPage}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
||||||
|
|
||||||
|
|
||||||
class MangahereTest(GenericComicReaderTest):
|
class MangahereTest(GenericComicReaderTest):
|
||||||
BACKEND = 'mangahere'
|
BACKEND = 'mangahere'
|
||||||
|
|
||||||
def test_download(self):
|
def test_download(self):
|
||||||
return self._test_download('glass_no_kamen/v02/c000')
|
return self._test_download('glass_no_kamen/v02/c000')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderBackend, DisplayPage
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderBackend, DisplayPage
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['MangareaderBackend']
|
__all__ = ['MangareaderBackend']
|
||||||
|
|
||||||
|
|
||||||
class MangareaderBackend(GenericComicReaderBackend):
|
class MangareaderBackend(GenericComicReaderBackend):
|
||||||
NAME = 'mangareader'
|
NAME = 'mangareader'
|
||||||
DESCRIPTION = 'MangaReader manga reading website'
|
DESCRIPTION = 'MangaReader manga reading website'
|
||||||
|
|
@ -31,4 +33,4 @@ class MangareaderBackend(GenericComicReaderBackend):
|
||||||
ID_REGEXP = r'[^/]+/[^/]+'
|
ID_REGEXP = r'[^/]+/[^/]+'
|
||||||
URL_REGEXP = r'.+mangareader.net/(%s).+' % ID_REGEXP
|
URL_REGEXP = r'.+mangareader.net/(%s).+' % ID_REGEXP
|
||||||
ID_TO_URL = 'http://www.mangareader.net/%s'
|
ID_TO_URL = 'http://www.mangareader.net/%s'
|
||||||
PAGES = { r'http://.+\.mangareader.net/.+': DisplayPage } # oh well
|
PAGES = {r'http://.+\.mangareader.net/.+': DisplayPage} # oh well
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
||||||
|
|
||||||
|
|
||||||
class MangareaderTest(GenericComicReaderTest):
|
class MangareaderTest(GenericComicReaderTest):
|
||||||
BACKEND = 'mangareader'
|
BACKEND = 'mangareader'
|
||||||
|
|
||||||
def test_download(self):
|
def test_download(self):
|
||||||
return self._test_download('glass-mask/3')
|
return self._test_download('glass-mask/3')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ from .browser import MediawikiBrowser
|
||||||
|
|
||||||
__all__ = ['MediawikiBackend']
|
__all__ = ['MediawikiBackend']
|
||||||
|
|
||||||
|
|
||||||
class MediawikiBackend(BaseBackend, ICapContent):
|
class MediawikiBackend(BaseBackend, ICapContent):
|
||||||
NAME = 'mediawiki'
|
NAME = 'mediawiki'
|
||||||
MAINTAINER = u'Clément Schreiner'
|
MAINTAINER = u'Clément Schreiner'
|
||||||
|
|
@ -42,6 +43,7 @@ class MediawikiBackend(BaseBackend, ICapContent):
|
||||||
ValueBackendPassword('password', label='Password', default=''))
|
ValueBackendPassword('password', label='Password', default=''))
|
||||||
|
|
||||||
BROWSER = MediawikiBrowser
|
BROWSER = MediawikiBrowser
|
||||||
|
|
||||||
def create_default_browser(self):
|
def create_default_browser(self):
|
||||||
username = self.config['username'].get()
|
username = self.config['username'].get()
|
||||||
if len(username) > 0:
|
if len(username) > 0:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ from urlparse import urlsplit
|
||||||
import urllib
|
import urllib
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword
|
from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword
|
||||||
from weboob.capabilities.content import Revision
|
from weboob.capabilities.content import Revision
|
||||||
|
|
||||||
|
|
@ -37,6 +36,7 @@ __all__ = ['MediawikiBrowser']
|
||||||
class APIError(Exception):
|
class APIError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Browser
|
# Browser
|
||||||
class MediawikiBrowser(BaseBrowser):
|
class MediawikiBrowser(BaseBrowser):
|
||||||
ENCODING = 'utf-8'
|
ENCODING = 'utf-8'
|
||||||
|
|
@ -63,8 +63,6 @@ class MediawikiBrowser(BaseBrowser):
|
||||||
'intoken': 'edit',
|
'intoken': 'edit',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
result = self.API_get(data)
|
result = self.API_get(data)
|
||||||
pageid = result['query']['pages'].keys()[0]
|
pageid = result['query']['pages'].keys()[0]
|
||||||
if pageid == "-1": # Page does not exist
|
if pageid == "-1": # Page does not exist
|
||||||
|
|
@ -83,8 +81,7 @@ class MediawikiBrowser(BaseBrowser):
|
||||||
}
|
}
|
||||||
result = self.API_get(data)
|
result = self.API_get(data)
|
||||||
pageid = result['query']['pages'].keys()[0]
|
pageid = result['query']['pages'].keys()[0]
|
||||||
return result['query']['pages'][str(pageid)][_type+'token']
|
return result['query']['pages'][str(pageid)][_type + 'token']
|
||||||
|
|
||||||
|
|
||||||
def set_wiki_source(self, content, message=None, minor=False):
|
def set_wiki_source(self, content, message=None, minor=False):
|
||||||
if len(self.username) > 0 and not self.is_logged():
|
if len(self.username) > 0 and not self.is_logged():
|
||||||
|
|
@ -138,7 +135,9 @@ class MediawikiBrowser(BaseBrowser):
|
||||||
self.API_post(data)
|
self.API_post(data)
|
||||||
|
|
||||||
def iter_wiki_revisions(self, page, nb_entries):
|
def iter_wiki_revisions(self, page, nb_entries):
|
||||||
'''Yield 'Revision' objects for the last <nb_entries> revisions of the specified page.'''
|
"""
|
||||||
|
Yield 'Revision' objects for the last <nb_entries> revisions of the specified page.
|
||||||
|
"""
|
||||||
if len(self.username) > 0 and not self.is_logged():
|
if len(self.username) > 0 and not self.is_logged():
|
||||||
self.login()
|
self.login()
|
||||||
data = {'action': 'query',
|
data = {'action': 'query',
|
||||||
|
|
@ -158,14 +157,11 @@ class MediawikiBrowser(BaseBrowser):
|
||||||
rev_content.revision = str(rev['revid'])
|
rev_content.revision = str(rev['revid'])
|
||||||
rev_content.author = rev['user']
|
rev_content.author = rev['user']
|
||||||
rev_content.timestamp = datetime.datetime.strptime(rev['timestamp'], '%Y-%m-%dT%H:%M:%SZ')
|
rev_content.timestamp = datetime.datetime.strptime(rev['timestamp'], '%Y-%m-%dT%H:%M:%SZ')
|
||||||
if rev.has_key('minor'):
|
rev_content.minor = 'minor' in rev
|
||||||
rev_content.minor = True
|
|
||||||
else:
|
|
||||||
rev_content.minor = False
|
|
||||||
yield rev_content
|
yield rev_content
|
||||||
|
|
||||||
def home(self):
|
def home(self):
|
||||||
'''We don't need to change location, we're using the JSON API here.'''
|
# We don't need to change location, we're using the JSON API here.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def check_result(self, result):
|
def check_result(self, result):
|
||||||
|
|
@ -173,17 +169,20 @@ class MediawikiBrowser(BaseBrowser):
|
||||||
raise APIError('%s' % result['error']['info'])
|
raise APIError('%s' % result['error']['info'])
|
||||||
|
|
||||||
def API_get(self, data):
|
def API_get(self, data):
|
||||||
'''Submit a GET request to the website
|
"""
|
||||||
The JSON data is parsed and returned as a dictionary'''
|
Submit a GET request to the website
|
||||||
|
The JSON data is parsed and returned as a dictionary
|
||||||
|
"""
|
||||||
data['format'] = 'json'
|
data['format'] = 'json'
|
||||||
result = simplejson.loads(self.readurl(self.buildurl(self.apiurl, **data)), 'utf-8')
|
result = simplejson.loads(self.readurl(self.buildurl(self.apiurl, **data)), 'utf-8')
|
||||||
self.check_result(result)
|
self.check_result(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def API_post(self, data):
|
def API_post(self, data):
|
||||||
'''Submit a POST request to the website
|
"""
|
||||||
The JSON data is parsed and returned as a dictionary'''
|
Submit a POST request to the website
|
||||||
|
The JSON data is parsed and returned as a dictionary
|
||||||
|
"""
|
||||||
data['format'] = 'json'
|
data['format'] = 'json'
|
||||||
result = simplejson.loads(self.readurl(self.apiurl, urllib.urlencode(data)), 'utf-8')
|
result = simplejson.loads(self.readurl(self.apiurl, urllib.urlencode(data)), 'utf-8')
|
||||||
self.check_result(result)
|
self.check_result(result)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from weboob.tools.browser import BasePage
|
from weboob.tools.browser import BasePage
|
||||||
from weboob.capabilities.weather import Forecast, Current, City
|
from weboob.capabilities.weather import Forecast, Current, City
|
||||||
|
|
||||||
|
|
@ -69,10 +68,10 @@ class WeatherPage(BasePage):
|
||||||
Return the city from the forecastpage.
|
Return the city from the forecastpage.
|
||||||
"""
|
"""
|
||||||
for div in self.document.getiterator('div'):
|
for div in self.document.getiterator('div'):
|
||||||
if div.attrib.has_key("class") and div.attrib.get("class") == "choix":
|
if div.attrib.get("class", "") == "choix":
|
||||||
for strong in div.getiterator("strong"):
|
for strong in div.getiterator("strong"):
|
||||||
city_name=strong.text +" "+ strong.tail.replace("(","").replace(")","")
|
city_name = strong.text + " " + strong.tail.replace("(", "").replace(")", "")
|
||||||
city_id=self.url.split("/")[-1]
|
city_id = self.url.split("/")[-1]
|
||||||
return City(city_id, city_name)
|
return City(city_id, city_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -84,5 +83,5 @@ class CityPage(BasePage):
|
||||||
city_name = li.text_content()
|
city_name = li.text_content()
|
||||||
for children in li.getchildren():
|
for children in li.getchildren():
|
||||||
city_id = children.attrib.get("href").split("/")[-1]
|
city_id = children.attrib.get("href").split("/")[-1]
|
||||||
mcity = City( city_id, city_name)
|
mcity = City(city_id, city_name)
|
||||||
yield mcity
|
yield mcity
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ from weboob.tools.capabilities.messages.GenericBackend import GenericNewspaperBa
|
||||||
from .browser import Newspaper20minutesBrowser
|
from .browser import Newspaper20minutesBrowser
|
||||||
from .tools import rssid
|
from .tools import rssid
|
||||||
|
|
||||||
|
|
||||||
class Newspaper20minutesBackend(GenericNewspaperBackend, ICapMessages):
|
class Newspaper20minutesBackend(GenericNewspaperBackend, ICapMessages):
|
||||||
MAINTAINER = 'Julien Hebert'
|
MAINTAINER = 'Julien Hebert'
|
||||||
EMAIL = 'juke@free.fr'
|
EMAIL = 'juke@free.fr'
|
||||||
|
|
@ -34,4 +35,3 @@ class Newspaper20minutesBackend(GenericNewspaperBackend, ICapMessages):
|
||||||
BROWSER = Newspaper20minutesBrowser
|
BROWSER = Newspaper20minutesBrowser
|
||||||
RSS_FEED = 'http://www.20minutes.fr/rss/20minutes.xml'
|
RSS_FEED = 'http://www.20minutes.fr/rss/20minutes.xml'
|
||||||
RSSID = rssid
|
RSSID = rssid
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
from weboob.tools.capabilities.messages.genericArticle import NoAuthorElement, try_remove, NoneMainDiv
|
from weboob.tools.capabilities.messages.genericArticle import NoAuthorElement, try_remove, NoneMainDiv
|
||||||
from .simple import SimplePage
|
from .simple import SimplePage
|
||||||
|
|
||||||
|
|
||||||
class ArticlePage(SimplePage):
|
class ArticlePage(SimplePage):
|
||||||
"ArticlePage object for minutes20"
|
"ArticlePage object for minutes20"
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
|
|
@ -37,9 +38,8 @@ class ArticlePage(SimplePage):
|
||||||
else:
|
else:
|
||||||
try_remove(self.parser, element_body, "div.mna-tools")
|
try_remove(self.parser, element_body, "div.mna-tools")
|
||||||
try_remove(self.parser, element_body, "div.mna-comment-call")
|
try_remove(self.parser, element_body, "div.mna-comment-call")
|
||||||
try :
|
try:
|
||||||
element_body.remove(self.get_element_author())
|
element_body.remove(self.get_element_author())
|
||||||
except NoAuthorElement:
|
except NoAuthorElement:
|
||||||
pass
|
pass
|
||||||
return self.parser.tostring(element_body)
|
return self.parser.tostring(element_body)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage
|
from weboob.tools.capabilities.messages.genericArticle import GenericNewsPage
|
||||||
|
|
||||||
|
|
||||||
class SimplePage(GenericNewsPage):
|
class SimplePage(GenericNewsPage):
|
||||||
"ArticlePage object for minutes20"
|
"ArticlePage object for minutes20"
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
|
|
@ -27,4 +28,3 @@ class SimplePage(GenericNewsPage):
|
||||||
self.element_title_selector = "h1"
|
self.element_title_selector = "h1"
|
||||||
self.element_author_selector = "div.mna-signature"
|
self.element_author_selector = "div.mna-signature"
|
||||||
self.element_body_selector = "div.mna-body"
|
self.element_body_selector = "div.mna-body"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,24 +18,27 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
def id2url(_id):
|
def id2url(_id):
|
||||||
"return an url from an id"
|
"return an url from an id"
|
||||||
regexp2 = re.compile("(\w+).([0-9]+).(.*$)")
|
regexp2 = re.compile("(\w+).([0-9]+).(.*$)")
|
||||||
match = regexp2.match(_id)
|
match = regexp2.match(_id)
|
||||||
if match:
|
if match:
|
||||||
return 'http://www.20minutes.fr/%s/%s/%s' % ( match.group(1),
|
return 'http://www.20minutes.fr/%s/%s/%s' % (match.group(1),
|
||||||
match.group(2),
|
match.group(2),
|
||||||
match.group(3))
|
match.group(3))
|
||||||
else:
|
else:
|
||||||
raise ValueError("id doesn't match")
|
raise ValueError("id doesn't match")
|
||||||
|
|
||||||
|
|
||||||
def url2id(url):
|
def url2id(url):
|
||||||
"return an id from an url"
|
"return an id from an url"
|
||||||
regexp = re.compile("http://www.20minutes.fr/(\w+)/([0-9]+)/(.*$)")
|
regexp = re.compile("http://www.20minutes.fr/(\w+)/([0-9]+)/(.*$)")
|
||||||
match = regexp.match(url)
|
match = regexp.match(url)
|
||||||
return '%s.%d.%s' % (match.group(1), int(match.group(2)), match.group(3))
|
return '%s.%d.%s' % (match.group(1), int(match.group(2)), match.group(3))
|
||||||
|
|
||||||
|
|
||||||
def rssid(entry):
|
def rssid(entry):
|
||||||
return url2id(entry.id)
|
return url2id(entry.id)
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@
|
||||||
|
|
||||||
from weboob.tools.test import BackendTest
|
from weboob.tools.test import BackendTest
|
||||||
|
|
||||||
|
|
||||||
class NewsfeedTest(BackendTest):
|
class NewsfeedTest(BackendTest):
|
||||||
BACKEND = 'newsfeed'
|
BACKEND = 'newsfeed'
|
||||||
|
|
||||||
def test_newsfeed(self):
|
def test_newsfeed(self):
|
||||||
for message in self.backend.iter_unread_messages():
|
for message in self.backend.iter_unread_messages():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ __all__ = ['VideoPage']
|
||||||
class ForbiddenVideo(Exception):
|
class ForbiddenVideo(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class VideoPage(BasePage):
|
|
||||||
|
|
||||||
|
class VideoPage(BasePage):
|
||||||
def get_video(self, video=None):
|
def get_video(self, video=None):
|
||||||
_id = to_unicode(self.group_dict['id'])
|
_id = to_unicode(self.group_dict['id'])
|
||||||
if video is None:
|
if video is None:
|
||||||
|
|
@ -84,4 +84,3 @@ class VideoPage(BasePage):
|
||||||
video.url = values['url']
|
video.url = values['url']
|
||||||
|
|
||||||
return video
|
return video
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,4 +67,3 @@ class AloesBackend(BaseBackend, ICapBook):
|
||||||
|
|
||||||
def search_books(self, _string):
|
def search_books(self, _string):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class AloesBrowser(BaseBrowser):
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, baseurl, *args, **kwargs):
|
def __init__(self, baseurl, *args, **kwargs):
|
||||||
self.BASEURL=baseurl
|
self.BASEURL = baseurl
|
||||||
BaseBrowser.__init__(self, *args, **kwargs)
|
BaseBrowser.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def is_logged(self):
|
def is_logged(self):
|
||||||
|
|
@ -60,10 +60,9 @@ class AloesBrowser(BaseBrowser):
|
||||||
no_login=True)
|
no_login=True)
|
||||||
if not self.page.login(self.username, self.password) or \
|
if not self.page.login(self.username, self.password) or \
|
||||||
not self.is_logged() or \
|
not self.is_logged() or \
|
||||||
(self.is_on_page(LoginPage) and self.page.is_error()) :
|
(self.is_on_page(LoginPage) and self.page.is_error()):
|
||||||
raise BrowserIncorrectPassword()
|
raise BrowserIncorrectPassword()
|
||||||
|
|
||||||
|
|
||||||
def get_rented_books_list(self):
|
def get_rented_books_list(self):
|
||||||
if not self.is_on_page(RentedPage):
|
if not self.is_on_page(RentedPage):
|
||||||
self.location('%s://%s/index.aspx?IdPage=45' \
|
self.location('%s://%s/index.aspx?IdPage=45' \
|
||||||
|
|
@ -73,6 +72,6 @@ class AloesBrowser(BaseBrowser):
|
||||||
|
|
||||||
def get_booked_books_list(self):
|
def get_booked_books_list(self):
|
||||||
if not self.is_on_page(BookedPage):
|
if not self.is_on_page(BookedPage):
|
||||||
self.location('%s://%s/index.aspx?IdPage=44' \
|
self.location('%s://%s/index.aspx?IdPage=44' \
|
||||||
% (self.PROTOCOL, self.BASEURL))
|
% (self.PROTOCOL, self.BASEURL))
|
||||||
return self.page.get_list()
|
return self.page.get_list()
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ from weboob.tools.browser import BasePage
|
||||||
|
|
||||||
__all__ = ['ComposePage', 'ConfirmPage']
|
__all__ = ['ComposePage', 'ConfirmPage']
|
||||||
|
|
||||||
|
|
||||||
class ConfirmPage(BasePage):
|
class ConfirmPage(BasePage):
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -33,9 +34,9 @@ class ComposePage(BasePage):
|
||||||
phone_regex = re.compile('^(\+33|0033|0)(6|7)(\d{8})$')
|
phone_regex = re.compile('^(\+33|0033|0)(6|7)(\d{8})$')
|
||||||
|
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
#Deal with bad encoding... for ie6 ...
|
# Deal with bad encoding... for ie6...
|
||||||
response = self.browser.response()
|
response = self.browser.response()
|
||||||
response.set_data(response.get_data().decode('utf-8', 'ignore') )
|
response.set_data(response.get_data().decode('utf-8', 'ignore'))
|
||||||
self.browser.set_response(response)
|
self.browser.set_response(response)
|
||||||
|
|
||||||
def get_nb_remaining_free_sms(self):
|
def get_nb_remaining_free_sms(self):
|
||||||
|
|
@ -46,12 +47,12 @@ class ComposePage(BasePage):
|
||||||
if self.phone_regex.match(receiver) is None:
|
if self.phone_regex.match(receiver) is None:
|
||||||
raise CantSendMessage(u'Invalid receiver: %s' % receiver)
|
raise CantSendMessage(u'Invalid receiver: %s' % receiver)
|
||||||
|
|
||||||
listetel = ",,"+ receiver
|
listetel = ",," + receiver
|
||||||
|
|
||||||
#Fill the form
|
#Fill the form
|
||||||
self.browser.select_form(name="formulaire")
|
self.browser.select_form(name="formulaire")
|
||||||
self.browser.new_control("hidden", "autorize",{'value':''})
|
self.browser.new_control("hidden", "autorize", {'value': ''})
|
||||||
self.browser.new_control("textarea", "msg", {'value':''})
|
self.browser.new_control("textarea", "msg", {'value': ''})
|
||||||
|
|
||||||
self.browser.set_all_readonly(False)
|
self.browser.set_all_readonly(False)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ class PastealaconBackend(BaseBackend, BasePasteBackend):
|
||||||
BROWSER = PastealaconBrowser
|
BROWSER = PastealaconBrowser
|
||||||
|
|
||||||
EXPIRATIONS = {
|
EXPIRATIONS = {
|
||||||
24*3600: 'd',
|
24 * 3600: 'd',
|
||||||
24*3600*30: 'm',
|
24 * 3600 * 30: 'm',
|
||||||
False: 'f',
|
False: 'f',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ class PastealaconBackend(BaseBackend, BasePasteBackend):
|
||||||
self.browser.fill_paste(paste)
|
self.browser.fill_paste(paste)
|
||||||
return paste
|
return paste
|
||||||
|
|
||||||
def post_paste(self, paste, max_age = None):
|
def post_paste(self, paste, max_age=None):
|
||||||
if max_age is not None:
|
if max_age is not None:
|
||||||
expiration = self.get_closest_expiration(max_age)
|
expiration = self.get_closest_expiration(max_age)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicRea
|
||||||
|
|
||||||
__all__ = ['SimplyreaditBackend']
|
__all__ = ['SimplyreaditBackend']
|
||||||
|
|
||||||
|
|
||||||
class SimplyreaditBackend(GenericComicReaderBackend):
|
class SimplyreaditBackend(GenericComicReaderBackend):
|
||||||
NAME = 'simplyreadit'
|
NAME = 'simplyreadit'
|
||||||
DESCRIPTION = 'SimplyReadIt manga reading website'
|
DESCRIPTION = 'SimplyReadIt manga reading website'
|
||||||
|
|
@ -30,4 +31,4 @@ class SimplyreaditBackend(GenericComicReaderBackend):
|
||||||
ID_TO_URL = 'http://www.simplyread.it/reader/read/%s'
|
ID_TO_URL = 'http://www.simplyread.it/reader/read/%s'
|
||||||
ID_REGEXP = r'[^/]+(?:/[^/]+)*'
|
ID_REGEXP = r'[^/]+(?:/[^/]+)*'
|
||||||
URL_REGEXP = r'.+simplyread.it/reader/read/(%s)/page/.+' % ID_REGEXP
|
URL_REGEXP = r'.+simplyread.it/reader/read/(%s)/page/.+' % ID_REGEXP
|
||||||
PAGES = { r'http://.+\.simplyread.it/reader/read/.+': DisplayPage }
|
PAGES = {r'http://.+\.simplyread.it/reader/read/.+': DisplayPage}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@
|
||||||
|
|
||||||
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderTest
|
||||||
|
|
||||||
|
|
||||||
class SimplyreaditTest(GenericComicReaderTest):
|
class SimplyreaditTest(GenericComicReaderTest):
|
||||||
BACKEND = 'simplyreadit'
|
BACKEND = 'simplyreadit'
|
||||||
|
|
||||||
def test_download(self):
|
def test_download(self):
|
||||||
return self._test_download('bonnouji/en/1/3')
|
return self._test_download('bonnouji/en/1/3')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,20 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import Image
|
import Image
|
||||||
|
|
||||||
|
|
||||||
class TileError(Exception):
|
class TileError(Exception):
|
||||||
def __init__(self, msg, tile = None):
|
def __init__(self, msg, tile=None):
|
||||||
Exception.__init__(self, msg)
|
Exception.__init__(self, msg)
|
||||||
self.tile = tile
|
self.tile = tile
|
||||||
|
|
||||||
class Captcha:
|
|
||||||
|
class Captcha(object):
|
||||||
def __init__(self, file, infos):
|
def __init__(self, file, infos):
|
||||||
self.inim = Image.open(file)
|
self.inim = Image.open(file)
|
||||||
self.infos = infos
|
self.infos = infos
|
||||||
self.nbr = int(infos["nblignes"])
|
self.nbr = int(infos["nblignes"])
|
||||||
self.nbc = int(infos["nbcolonnes"])
|
self.nbc = int(infos["nbcolonnes"])
|
||||||
(self.nx,self.ny) = self.inim.size
|
(self.nx, self.ny) = self.inim.size
|
||||||
self.inmat = self.inim.load()
|
self.inmat = self.inim.load()
|
||||||
self.map = {}
|
self.map = {}
|
||||||
|
|
||||||
|
|
@ -77,7 +79,7 @@ class Captcha:
|
||||||
self.map[num] = tile
|
self.map[num] = tile
|
||||||
|
|
||||||
|
|
||||||
class Tile:
|
class Tile(object):
|
||||||
hash = {'ff1441b2c5f90703ef04e688e399aca5': 1,
|
hash = {'ff1441b2c5f90703ef04e688e399aca5': 1,
|
||||||
'53d7f3dfd64f54723b231fc398b6be57': 2,
|
'53d7f3dfd64f54723b231fc398b6be57': 2,
|
||||||
'5bcba7fa2107ba9a606e8d0131c162eb': 3,
|
'5bcba7fa2107ba9a606e8d0131c162eb': 3,
|
||||||
|
|
@ -116,4 +118,3 @@ class Tile:
|
||||||
|
|
||||||
def display(self):
|
def display(self):
|
||||||
print self.checksum()
|
print self.checksum()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@
|
||||||
from .accounts_list import AccountsList
|
from .accounts_list import AccountsList
|
||||||
from .login import LoginPage, BadLoginPage
|
from .login import LoginPage, BadLoginPage
|
||||||
|
|
||||||
class AccountPrelevement(AccountsList): pass
|
|
||||||
|
class AccountPrelevement(AccountsList):
|
||||||
|
pass
|
||||||
|
|
||||||
__all__ = ['LoginPage',
|
__all__ = ['LoginPage',
|
||||||
'BadLoginPage',
|
'BadLoginPage',
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,11 @@ class LoginPage(BasePage):
|
||||||
infos_xml = etree.XML(infos_data)
|
infos_xml = etree.XML(infos_data)
|
||||||
infos = {}
|
infos = {}
|
||||||
for el in ("cryptogramme", "nblignes", "nbcolonnes"):
|
for el in ("cryptogramme", "nblignes", "nbcolonnes"):
|
||||||
infos[el] = infos_xml.find(el).text
|
infos[el] = infos_xml.find(el).text
|
||||||
|
|
||||||
infos["grille"] = ""
|
infos["grille"] = ""
|
||||||
for g in infos_xml.findall("grille"):
|
for g in infos_xml.findall("grille"):
|
||||||
infos["grille"] += g.text + ","
|
infos["grille"] += g.text + ","
|
||||||
infos["keyCodes"] = infos["grille"].split(",")
|
infos["keyCodes"] = infos["grille"].split(",")
|
||||||
|
|
||||||
url = base_url + '/cvcsgenimage?modeClavier=0&cryptogramme=' + infos["cryptogramme"]
|
url = base_url + '/cvcsgenimage?modeClavier=0&cryptogramme=' + infos["cryptogramme"]
|
||||||
|
|
@ -79,5 +79,6 @@ class LoginPage(BasePage):
|
||||||
self.browser['cryptocvcs'] = infos["cryptogramme"]
|
self.browser['cryptocvcs'] = infos["cryptogramme"]
|
||||||
self.browser.submit()
|
self.browser.submit()
|
||||||
|
|
||||||
|
|
||||||
class BadLoginPage(BasePage):
|
class BadLoginPage(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,3 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,4 +63,3 @@ class VideoPage(BasePage):
|
||||||
video.url = video_file_urls[0]
|
video.url = video_file_urls[0]
|
||||||
|
|
||||||
return video
|
return video
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ class YoupornBackend(BaseBackend, ICapVideo):
|
||||||
return self.browser.get_video(_id)
|
return self.browser.get_video(_id)
|
||||||
|
|
||||||
SORTBY = ['relevance', 'rating', 'views', 'time']
|
SORTBY = ['relevance', 'rating', 'views', 'time']
|
||||||
|
|
||||||
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
|
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
|
||||||
if not nsfw:
|
if not nsfw:
|
||||||
return set()
|
return set()
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ class LoginPage(BasePage):
|
||||||
self.browser['Passwd'] = password
|
self.browser['Passwd'] = password
|
||||||
self.browser.submit()
|
self.browser.submit()
|
||||||
|
|
||||||
|
|
||||||
class LoginRedirectPage(BasePage):
|
class LoginRedirectPage(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -64,6 +65,7 @@ class BaseYoutubePage(BasePage):
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ForbiddenVideoPage(BaseYoutubePage):
|
class ForbiddenVideoPage(BaseYoutubePage):
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
element = self.parser.select(self.document.getroot(), '.yt-alert-content', 1)
|
element = self.parser.select(self.document.getroot(), '.yt-alert-content', 1)
|
||||||
|
|
@ -78,11 +80,13 @@ class VerifyAgePage(BaseYoutubePage):
|
||||||
self.browser.select_form(predicate=lambda form: form.attrs.get('id', '') == 'confirm-age-form')
|
self.browser.select_form(predicate=lambda form: form.attrs.get('id', '') == 'confirm-age-form')
|
||||||
self.browser.submit()
|
self.browser.submit()
|
||||||
|
|
||||||
|
|
||||||
class VerifyControversyPage(BaseYoutubePage):
|
class VerifyControversyPage(BaseYoutubePage):
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
self.browser.select_form(predicate=lambda form: 'verify_controversy' in form.attrs.get('action', ''))
|
self.browser.select_form(predicate=lambda form: 'verify_controversy' in form.attrs.get('action', ''))
|
||||||
self.browser.submit()
|
self.browser.submit()
|
||||||
|
|
||||||
|
|
||||||
class VideoPage(BaseYoutubePage):
|
class VideoPage(BaseYoutubePage):
|
||||||
AVAILABLE_FORMATS = [38, 37, 45, 22, 43, 35, 34, 18, 6, 5, 17, 13]
|
AVAILABLE_FORMATS = [38, 37, 45, 22, 43, 35, 34, 18, 6, 5, 17, 13]
|
||||||
FORMAT_EXTENSIONS = {
|
FORMAT_EXTENSIONS = {
|
||||||
|
|
@ -91,7 +95,7 @@ class VideoPage(BaseYoutubePage):
|
||||||
18: 'mp4',
|
18: 'mp4',
|
||||||
22: 'mp4',
|
22: 'mp4',
|
||||||
37: 'mp4',
|
37: 'mp4',
|
||||||
38: 'video', # You actually don't know if this will be MOV, AVI or whatever
|
38: 'video', # You actually don't know if this will be MOV, AVI or whatever
|
||||||
43: 'webm',
|
43: 'webm',
|
||||||
45: 'webm',
|
45: 'webm',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
26
setup.py
26
setup.py
|
|
@ -38,7 +38,7 @@ def check_executable_win(executable, error):
|
||||||
path = filter(None, path.split(";"))
|
path = filter(None, path.split(";"))
|
||||||
|
|
||||||
if dotfirst:
|
if dotfirst:
|
||||||
path = ["."]+path
|
path = ["."] + path
|
||||||
|
|
||||||
pathext = os.environ[pathextsrc]
|
pathext = os.environ[pathextsrc]
|
||||||
pathext = filter(None, pathext.split(";"))
|
pathext = filter(None, pathext.split(";"))
|
||||||
|
|
@ -56,13 +56,14 @@ def check_executable_win(executable, error):
|
||||||
for e in pathext:
|
for e in pathext:
|
||||||
filePath = os.path.join(d, cmdName + e)
|
filePath = os.path.join(d, cmdName + e)
|
||||||
if os.path.exists(filePath):
|
if os.path.exists(filePath):
|
||||||
return filePath.replace( '\\', '/' )
|
return filePath.replace('\\', '/')
|
||||||
|
|
||||||
print >>sys.stderr, 'Error: %s is not installed on your system.' % executable
|
print >>sys.stderr, 'Error: %s is not installed on your system.' % executable
|
||||||
if error:
|
if error:
|
||||||
print >>sys.stderr, error
|
print >>sys.stderr, error
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def check_executable_unix(executable, error):
|
def check_executable_unix(executable, error):
|
||||||
with open('/dev/null', 'w') as devnull:
|
with open('/dev/null', 'w') as devnull:
|
||||||
process = subprocess.Popen(['which', executable], stdout=devnull)
|
process = subprocess.Popen(['which', executable], stdout=devnull)
|
||||||
|
|
@ -80,28 +81,31 @@ if sys.platform == 'win32':
|
||||||
else:
|
else:
|
||||||
check_executable = check_executable_unix
|
check_executable = check_executable_unix
|
||||||
|
|
||||||
|
|
||||||
def build_qt():
|
def build_qt():
|
||||||
print 'Building Qt applications'
|
print 'Building Qt applications'
|
||||||
pyuic4 = check_executable('pyuic4', 'Install PyQt4-devel or disable Qt applications (with --no-qt).')
|
pyuic4 = check_executable('pyuic4', 'Install PyQt4-devel or disable Qt applications (with --no-qt).')
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
env={ 'PYUIC' : pyuic4, 'PATH':os.environ['PATH']}
|
env = {'PYUIC': pyuic4, 'PATH': os.environ['PATH']}
|
||||||
extraMakeFlag = ['-e']
|
extraMakeFlag = ['-e']
|
||||||
else:
|
else:
|
||||||
env = None
|
env = None
|
||||||
extraMakeFlag = []
|
extraMakeFlag = []
|
||||||
|
|
||||||
subprocess.check_call(['make']+extraMakeFlag+['-C','weboob/applications/qboobmsg/ui'], env=env )
|
subprocess.check_call(['make']+extraMakeFlag+['-C', 'weboob/applications/qboobmsg/ui'], env=env)
|
||||||
subprocess.check_call(['make']+extraMakeFlag+['-C','weboob/applications/qhavedate/ui'], env=env )
|
subprocess.check_call(['make']+extraMakeFlag+['-C', 'weboob/applications/qhavedate/ui'], env=env)
|
||||||
if sys.platform != 'win32':
|
if sys.platform != 'win32':
|
||||||
subprocess.check_call(['make']+extraMakeFlag+['-C','weboob/applications/qvideoob/ui'], env=env )
|
subprocess.check_call(['make']+extraMakeFlag+['-C', 'weboob/applications/qvideoob/ui'], env=env)
|
||||||
subprocess.check_call(['make']+extraMakeFlag+['-C','weboob/applications/qwebcontentedit/ui'], env=env )
|
subprocess.check_call(['make']+extraMakeFlag+['-C', 'weboob/applications/qwebcontentedit/ui'], env=env)
|
||||||
subprocess.check_call(['make']+extraMakeFlag+['-C','weboob/applications/qflatboob/ui'], env=env )
|
subprocess.check_call(['make']+extraMakeFlag+['-C', 'weboob/applications/qflatboob/ui'], env=env)
|
||||||
subprocess.check_call(['make']+extraMakeFlag+['-C','weboob/tools/application/qt'], env=env )
|
subprocess.check_call(['make']+extraMakeFlag+['-C', 'weboob/tools/application/qt'], env=env)
|
||||||
|
|
||||||
class Options:
|
|
||||||
|
class Options(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
options = Options()
|
options = Options()
|
||||||
options.hildon = False
|
options.hildon = False
|
||||||
options.qt = True
|
options.qt = True
|
||||||
|
|
@ -189,7 +193,7 @@ if options.xdg:
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='weboob',
|
name='weboob',
|
||||||
version = '0.b',
|
version='0.b',
|
||||||
description='Weboob, Web Out Of Browsers',
|
description='Weboob, Web Out Of Browsers',
|
||||||
long_description=open('README').read(),
|
long_description=open('README').read(),
|
||||||
author='Romain Bignon',
|
author='Romain Bignon',
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,11 @@
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
import sys, os, tempfile
|
import sys
|
||||||
import imp, inspect
|
import os
|
||||||
|
import tempfile
|
||||||
|
import imp
|
||||||
|
import inspect
|
||||||
import optparse
|
import optparse
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
@ -31,8 +34,9 @@ from weboob.tools.application.base import BaseApplication
|
||||||
BASE_PATH = os.path.join(os.path.dirname(__file__), os.pardir)
|
BASE_PATH = os.path.join(os.path.dirname(__file__), os.pardir)
|
||||||
DEST_DIR = 'man'
|
DEST_DIR = 'man'
|
||||||
|
|
||||||
|
|
||||||
class ManpageHelpFormatter(optparse.HelpFormatter):
|
class ManpageHelpFormatter(optparse.HelpFormatter):
|
||||||
def __init__ (self,
|
def __init__(self,
|
||||||
app,
|
app,
|
||||||
indent_increment=0,
|
indent_increment=0,
|
||||||
max_help_position=0,
|
max_help_position=0,
|
||||||
|
|
@ -94,7 +98,7 @@ class ManpageHelpFormatter(optparse.HelpFormatter):
|
||||||
def format_option_strings(self, option):
|
def format_option_strings(self, option):
|
||||||
opts = optparse.HelpFormatter.format_option_strings(self, option).split(", ")
|
opts = optparse.HelpFormatter.format_option_strings(self, option).split(", ")
|
||||||
|
|
||||||
return ".TP\n"+", ".join("\\fB%s\\fR" % opt for opt in opts)
|
return ".TP\n" + ", ".join("\\fB%s\\fR" % opt for opt in opts)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -129,17 +133,21 @@ def main():
|
||||||
analyze_application(klass, fname)
|
analyze_application(klass, fname)
|
||||||
finally:
|
finally:
|
||||||
# Cleanup compiled files if needed
|
# Cleanup compiled files if needed
|
||||||
if (os.path.isfile(tmpfile+"c")):
|
if (os.path.isfile(tmpfile + "c")):
|
||||||
os.unlink(tmpfile+"c")
|
os.unlink(tmpfile + "c")
|
||||||
|
|
||||||
|
|
||||||
def format_title(title):
|
def format_title(title):
|
||||||
return re.sub(r'^(.+):$', r'.SH \1\n.TP', title.group().upper())
|
return re.sub(r'^(.+):$', r'.SH \1\n.TP', title.group().upper())
|
||||||
|
|
||||||
|
|
||||||
# XXX useful because the PyQt QApplication destructor crashes sometimes. By
|
# XXX useful because the PyQt QApplication destructor crashes sometimes. By
|
||||||
# keeping every applications until program end, it prevents to stop before
|
# keeping every applications until program end, it prevents to stop before
|
||||||
# every manpages have been generated. If it crashes at exit, it's not a
|
# every manpages have been generated. If it crashes at exit, it's not a
|
||||||
# really a problem.
|
# really a problem.
|
||||||
applications = []
|
applications = []
|
||||||
|
|
||||||
|
|
||||||
def analyze_application(app, script_name):
|
def analyze_application(app, script_name):
|
||||||
application = app()
|
application = app()
|
||||||
applications.append(application)
|
applications.append(application)
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -49,6 +49,7 @@ class QifFormatter(IFormatter):
|
||||||
self.count += 1
|
self.count += 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class TransactionsFormatter(IFormatter):
|
class TransactionsFormatter(IFormatter):
|
||||||
MANDATORY_FIELDS = ('date', 'label', 'amount')
|
MANDATORY_FIELDS = ('date', 'label', 'amount')
|
||||||
TYPES = ['', 'Transfer', 'Order', 'Check', 'Deposit', 'Payback', 'Withdrawal', 'Card', 'Loan', 'Bank']
|
TYPES = ['', 'Transfer', 'Order', 'Check', 'Deposit', 'Payback', 'Withdrawal', 'Card', 'Loan', 'Bank']
|
||||||
|
|
@ -82,6 +83,7 @@ class TransactionsFormatter(IFormatter):
|
||||||
result += ' %-10s %-12s %-50s %10.2f' % (item['date'].strftime('%Y-%m-%d'), _type, label[:50], item['amount'])
|
result += ' %-10s %-12s %-50s %10.2f' % (item['date'].strftime('%Y-%m-%d'), _type, label[:50], item['amount'])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class TransferFormatter(IFormatter):
|
class TransferFormatter(IFormatter):
|
||||||
MANDATORY_FIELDS = ('id', 'date', 'origin', 'recipient', 'amount')
|
MANDATORY_FIELDS = ('id', 'date', 'origin', 'recipient', 'amount')
|
||||||
|
|
||||||
|
|
@ -96,6 +98,7 @@ class TransferFormatter(IFormatter):
|
||||||
result += u'Amount: %.2f\n' % item['amount']
|
result += u'Amount: %.2f\n' % item['amount']
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class RecipientListFormatter(IFormatter):
|
class RecipientListFormatter(IFormatter):
|
||||||
MANDATORY_FIELDS = ('id', 'label')
|
MANDATORY_FIELDS = ('id', 'label')
|
||||||
|
|
||||||
|
|
@ -115,6 +118,7 @@ class RecipientListFormatter(IFormatter):
|
||||||
|
|
||||||
return u'%s %-30s %s %s' % (self.BOLD, id, self.NC, item['label'])
|
return u'%s %-30s %s %s' % (self.BOLD, id, self.NC, item['label'])
|
||||||
|
|
||||||
|
|
||||||
class AccountListFormatter(IFormatter):
|
class AccountListFormatter(IFormatter):
|
||||||
MANDATORY_FIELDS = ('id', 'label', 'balance', 'coming')
|
MANDATORY_FIELDS = ('id', 'label', 'balance', 'coming')
|
||||||
|
|
||||||
|
|
@ -122,13 +126,12 @@ class AccountListFormatter(IFormatter):
|
||||||
tot_balance = 0.0
|
tot_balance = 0.0
|
||||||
tot_coming = 0.0
|
tot_coming = 0.0
|
||||||
|
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
if self.count < 1:
|
if self.count < 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
result = u'------------------------------------------%s+----------+----------\n' % (('-' * 15) if not self.interactive else '')
|
result = u'------------------------------------------%s+----------+----------\n' % (('-' * 15) if not self.interactive else '')
|
||||||
result +=u'%s Total %8s %8s' % ((' ' * 15) if not self.interactive else '',
|
result += u'%s Total %8s %8s' % ((' ' * 15) if not self.interactive else '',
|
||||||
'%.2f' % self.tot_balance, '%.2f' % self.tot_coming)
|
'%.2f' % self.tot_balance, '%.2f' % self.tot_coming)
|
||||||
self.after_format(result)
|
self.after_format(result)
|
||||||
self.tot_balance = 0.0
|
self.tot_balance = 0.0
|
||||||
|
|
@ -156,6 +159,7 @@ class AccountListFormatter(IFormatter):
|
||||||
self.tot_coming += item['coming']
|
self.tot_coming += item['coming']
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Boobank(ReplApplication):
|
class Boobank(ReplApplication):
|
||||||
APPNAME = 'boobank'
|
APPNAME = 'boobank'
|
||||||
VERSION = '0.b'
|
VERSION = '0.b'
|
||||||
|
|
@ -278,7 +282,7 @@ class Boobank(ReplApplication):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
amount = float(amount)
|
amount = float(amount)
|
||||||
except (TypeError,ValueError):
|
except (TypeError, ValueError):
|
||||||
print >>sys.stderr, 'Error: please give a decimal amount to transfer'
|
print >>sys.stderr, 'Error: please give a decimal amount to transfer'
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ class MasstransitHildon():
|
||||||
self.main_window.connect("destroy", self.on_main_window_destroy)
|
self.main_window.connect("destroy", self.on_main_window_destroy)
|
||||||
|
|
||||||
self.refresh_button.connect("clicked", self.on_refresh_button_clicked)
|
self.refresh_button.connect("clicked", self.on_refresh_button_clicked)
|
||||||
|
|
||||||
self.retour_button.set_sensitive(False)
|
self.retour_button.set_sensitive(False)
|
||||||
self.retour_button.connect("clicked", self.on_retour_button_clicked)
|
self.retour_button.connect("clicked", self.on_retour_button_clicked)
|
||||||
|
|
||||||
|
|
@ -165,8 +165,8 @@ class MasstransitHildon():
|
||||||
text=4
|
text=4
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vertical_box = gtk.VBox()
|
vertical_box = gtk.VBox()
|
||||||
vertical_box.pack_start(horizontal_box)
|
vertical_box.pack_start(horizontal_box)
|
||||||
horizontal_box.pack_start(self.retour_button)
|
horizontal_box.pack_start(self.retour_button)
|
||||||
|
|
@ -187,7 +187,7 @@ class MasstransitHildon():
|
||||||
|
|
||||||
def fill_touch_selector_entry(self):
|
def fill_touch_selector_entry(self):
|
||||||
liste = []
|
liste = []
|
||||||
|
|
||||||
for backend in self.weboob.iter_backends():
|
for backend in self.weboob.iter_backends():
|
||||||
for station in backend.iter_station_search(""):
|
for station in backend.iter_station_search(""):
|
||||||
liste.append(station.name.capitalize())
|
liste.append(station.name.capitalize())
|
||||||
|
|
@ -272,7 +272,7 @@ class MasstransitHildon():
|
||||||
|
|
||||||
self.refresh_in_progress = False
|
self.refresh_in_progress = False
|
||||||
banner.set_timeout(1)
|
banner.set_timeout(1)
|
||||||
hildon.hildon_gtk_window_set_progress_indicator(self.main_window, 0)
|
hildon.hildon_gtk_window_set_progress_indicator(self.main_window, 0)
|
||||||
|
|
||||||
|
|
||||||
class Masstransit(BaseApplication):
|
class Masstransit(BaseApplication):
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
from .qwebcontentedit import QWebContentEdit
|
from .qwebcontentedit import QWebContentEdit
|
||||||
|
|
||||||
__all__ = ['QWebContentEdit']
|
|
||||||
|
__all__ = ['QWebContentEdit']
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from weboob.capabilities.content import ICapContent
|
||||||
|
|
||||||
from .main_window import MainWindow
|
from .main_window import MainWindow
|
||||||
|
|
||||||
|
|
||||||
class QWebContentEdit(QtApplication):
|
class QWebContentEdit(QtApplication):
|
||||||
APPNAME = 'qwebcontentedit'
|
APPNAME = 'qwebcontentedit'
|
||||||
VERSION = '0.b'
|
VERSION = '0.b'
|
||||||
|
|
@ -34,5 +35,3 @@ class QWebContentEdit(QtApplication):
|
||||||
self.main_window = MainWindow(self.config, self.weboob)
|
self.main_window = MainWindow(self.config, self.weboob)
|
||||||
self.main_window.show()
|
self.main_window.show()
|
||||||
return self.weboob.loop()
|
return self.weboob.loop()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,8 +124,8 @@ class WeboobRepos(ReplApplication):
|
||||||
'--keyring', os.path.realpath(krname),
|
'--keyring', os.path.realpath(krname),
|
||||||
'--import', os.path.realpath(keypath)])
|
'--import', os.path.realpath(keypath)])
|
||||||
# Does not make much sense in our case
|
# Does not make much sense in our case
|
||||||
if os.path.exists(krname+'~'):
|
if os.path.exists(krname + '~'):
|
||||||
os.remove(krname+'~')
|
os.remove(krname + '~')
|
||||||
if not os.path.exists(krname):
|
if not os.path.exists(krname):
|
||||||
raise Exception('No valid key file found.')
|
raise Exception('No valid key file found.')
|
||||||
kr_mtime = mktime(strptime(str(r.key_update), '%Y%m%d%H%M'))
|
kr_mtime = mktime(strptime(str(r.key_update), '%Y%m%d%H%M'))
|
||||||
|
|
@ -134,7 +134,6 @@ class WeboobRepos(ReplApplication):
|
||||||
else:
|
else:
|
||||||
print 'Keyring is up to date'
|
print 'Keyring is up to date'
|
||||||
|
|
||||||
|
|
||||||
for name, module in r.modules.iteritems():
|
for name, module in r.modules.iteritems():
|
||||||
tarname = os.path.join(repo_path, '%s.tar.gz' % name)
|
tarname = os.path.join(repo_path, '%s.tar.gz' % name)
|
||||||
if r.signed:
|
if r.signed:
|
||||||
|
|
@ -185,7 +184,7 @@ class WeboobRepos(ReplApplication):
|
||||||
# Check if all files have an up to date signature
|
# Check if all files have an up to date signature
|
||||||
for filename in sigfiles:
|
for filename in sigfiles:
|
||||||
filepath = os.path.realpath(os.path.join(repo_path, filename))
|
filepath = os.path.realpath(os.path.join(repo_path, filename))
|
||||||
sigpath = filepath+'.sig'
|
sigpath = filepath + '.sig'
|
||||||
file_mtime = int(os.path.getmtime(filepath))
|
file_mtime = int(os.path.getmtime(filepath))
|
||||||
if os.path.exists(sigpath):
|
if os.path.exists(sigpath):
|
||||||
sig_mtime = int(os.path.getmtime(sigpath))
|
sig_mtime = int(os.path.getmtime(sigpath))
|
||||||
|
|
@ -202,7 +201,6 @@ class WeboobRepos(ReplApplication):
|
||||||
os.utime(sigpath, (file_mtime, file_mtime))
|
os.utime(sigpath, (file_mtime, file_mtime))
|
||||||
print 'Signatures are up to date'
|
print 'Signatures are up to date'
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _find_gpg():
|
def _find_gpg():
|
||||||
if os.getenv('GPG_EXECUTABLE'):
|
if os.getenv('GPG_EXECUTABLE'):
|
||||||
|
|
@ -221,4 +219,3 @@ class WeboobRepos(ReplApplication):
|
||||||
if filename.endswith('.png'):
|
if filename.endswith('.png'):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ class NotLoaded(object):
|
||||||
class IBaseCap(object):
|
class IBaseCap(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CapBaseObject(object):
|
class CapBaseObject(object):
|
||||||
FIELDS = None
|
FIELDS = None
|
||||||
_attribs = None
|
_attribs = None
|
||||||
|
|
@ -128,7 +129,7 @@ class CapBaseObject(object):
|
||||||
if self.FIELDS is None:
|
if self.FIELDS is None:
|
||||||
yield 'id', self.id
|
yield 'id', self.id
|
||||||
for key, value in iter_fields(self):
|
for key, value in iter_fields(self):
|
||||||
if key not in ('id', 'backend','FIELDS'):
|
if key not in ('id', 'backend', 'FIELDS'):
|
||||||
yield key, value
|
yield key, value
|
||||||
else:
|
else:
|
||||||
yield 'id', self.id
|
yield 'id', self.id
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ from weboob.tools.ordereddict import OrderedDict
|
||||||
|
|
||||||
__all__ = ['ICapContact', 'Contact']
|
__all__ = ['ICapContact', 'Contact']
|
||||||
|
|
||||||
|
|
||||||
class ProfileNode(object):
|
class ProfileNode(object):
|
||||||
HEAD = 0x01
|
HEAD = 0x01
|
||||||
SECTION = 0x02
|
SECTION = 0x02
|
||||||
|
|
@ -38,6 +39,7 @@ class ProfileNode(object):
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.value[key]
|
return self.value[key]
|
||||||
|
|
||||||
|
|
||||||
class ContactPhoto(CapBaseObject):
|
class ContactPhoto(CapBaseObject):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
CapBaseObject.__init__(self, name)
|
CapBaseObject.__init__(self, name)
|
||||||
|
|
@ -59,6 +61,7 @@ class ContactPhoto(CapBaseObject):
|
||||||
len(self.data) if self.data else 0,
|
len(self.data) if self.data else 0,
|
||||||
len(self.thumbnail_data) if self.thumbnail_data else 0)
|
len(self.thumbnail_data) if self.thumbnail_data else 0)
|
||||||
|
|
||||||
|
|
||||||
class Contact(CapBaseObject):
|
class Contact(CapBaseObject):
|
||||||
STATUS_ONLINE = 0x001
|
STATUS_ONLINE = 0x001
|
||||||
STATUS_AWAY = 0x002
|
STATUS_AWAY = 0x002
|
||||||
|
|
@ -83,14 +86,17 @@ class Contact(CapBaseObject):
|
||||||
for key, value in kwargs.iteritems():
|
for key, value in kwargs.iteritems():
|
||||||
setattr(photo, key, value)
|
setattr(photo, key, value)
|
||||||
|
|
||||||
|
|
||||||
class QueryError(Exception):
|
class QueryError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Query(CapBaseObject):
|
class Query(CapBaseObject):
|
||||||
def __init__(self, id, message):
|
def __init__(self, id, message):
|
||||||
CapBaseObject.__init__(self, id)
|
CapBaseObject.__init__(self, id)
|
||||||
self.add_field('message', basestring, message)
|
self.add_field('message', basestring, message)
|
||||||
|
|
||||||
|
|
||||||
class ICapContact(IBaseCap):
|
class ICapContact(IBaseCap):
|
||||||
def iter_contacts(self, status=Contact.STATUS_ALL, ids=None):
|
def iter_contacts(self, status=Contact.STATUS_ALL, ids=None):
|
||||||
"""
|
"""
|
||||||
|
|
@ -129,20 +135,20 @@ class ICapContact(IBaseCap):
|
||||||
@except QueryError
|
@except QueryError
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def get_notes(self, id):
|
def get_notes(self, id):
|
||||||
"""
|
"""
|
||||||
Get personal notes about a contact
|
Get personal notes about a contact
|
||||||
|
|
||||||
@param id the ID of the contact
|
@param id the ID of the contact
|
||||||
@return a unicode object
|
@return a unicode object
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def save_notes(self, id, notes):
|
def save_notes(self, id, notes):
|
||||||
"""
|
"""
|
||||||
Set personal notes about a contact
|
Set personal notes about a contact
|
||||||
|
|
||||||
@param id the ID of the contact
|
@param id the ID of the contact
|
||||||
@param notes the unicode object to save as notes
|
@param notes the unicode object to save as notes
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,11 @@ from logging import warning
|
||||||
|
|
||||||
__all__ = ['BackendsConfig', 'BackendAlreadyExists']
|
__all__ = ['BackendsConfig', 'BackendAlreadyExists']
|
||||||
|
|
||||||
|
|
||||||
class BackendAlreadyExists(Exception):
|
class BackendAlreadyExists(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BackendsConfig(object):
|
class BackendsConfig(object):
|
||||||
class WrongPermissions(Exception):
|
class WrongPermissions(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
@ -41,13 +43,13 @@ class BackendsConfig(object):
|
||||||
mode = os.stat(confpath).st_mode
|
mode = os.stat(confpath).st_mode
|
||||||
except OSError:
|
except OSError:
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
fptr = open(confpath,'w')
|
fptr = open(confpath, 'w')
|
||||||
fptr.close()
|
fptr.close()
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
os.mknod(confpath, 0600)
|
os.mknod(confpath, 0600)
|
||||||
except OSError:
|
except OSError:
|
||||||
fptr = open(confpath,'w')
|
fptr = open(confpath, 'w')
|
||||||
fptr.close()
|
fptr.close()
|
||||||
os.chmod(confpath, 0600)
|
os.chmod(confpath, 0600)
|
||||||
else:
|
else:
|
||||||
|
|
@ -129,5 +131,3 @@ class BackendsConfig(object):
|
||||||
with open(self.confpath, 'w') as f:
|
with open(self.confpath, 'w') as f:
|
||||||
config.write(f)
|
config.write(f)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ class Versions(object):
|
||||||
with open(os.path.join(self.path, self.VERSIONS_LIST), 'wb') as fp:
|
with open(os.path.join(self.path, self.VERSIONS_LIST), 'wb') as fp:
|
||||||
config.write(fp)
|
config.write(fp)
|
||||||
|
|
||||||
class IProgress:
|
class IProgress(object):
|
||||||
def progress(self, percent, message):
|
def progress(self, percent, message):
|
||||||
print '=== [%3.0f%%] %s' % (percent*100, message)
|
print '=== [%3.0f%%] %s' % (percent*100, message)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ class IFormatter(object):
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
self.termrows = WConio.gettextinfo()[8]
|
self.termrows = WConio.gettextinfo()[8]
|
||||||
else:
|
else:
|
||||||
self.termrows = int( subprocess.Popen('stty size', shell=True, stdout=subprocess.PIPE).communicate()[0].split()[0])
|
self.termrows = int(subprocess.Popen('stty size', shell=True, stdout=subprocess.PIPE).communicate()[0].split()[0])
|
||||||
|
|
||||||
def after_format(self, formatted):
|
def after_format(self, formatted):
|
||||||
if self.outfile != sys.stdout:
|
if self.outfile != sys.stdout:
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ class WebBrowser(gtk.Window):
|
||||||
self.connect('destroy', gtk.main_quit)
|
self.connect('destroy', gtk.main_quit)
|
||||||
self.set_default_size(800, 600)
|
self.set_default_size(800, 600)
|
||||||
self.web_view = webkit.WebView()
|
self.web_view = webkit.WebView()
|
||||||
sw = gtk.ScrolledWindow()
|
sw = gtk.ScrolledWindow()
|
||||||
sw.add(self.web_view)
|
sw.add(self.web_view)
|
||||||
self.add(sw)
|
self.add(sw)
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ class BackendStorage(object):
|
||||||
if self.storage:
|
if self.storage:
|
||||||
return self.storage.save('backends', self.name)
|
return self.storage.save('backends', self.name)
|
||||||
|
|
||||||
|
|
||||||
class BackendConfig(ValuesDict):
|
class BackendConfig(ValuesDict):
|
||||||
modname = None
|
modname = None
|
||||||
instname = None
|
instname = None
|
||||||
|
|
@ -118,6 +119,7 @@ class BackendConfig(ValuesDict):
|
||||||
|
|
||||||
self.weboob.backends_config.add_backend(self.instname, self.modname, dump, edit)
|
self.weboob.backends_config.add_backend(self.instname, self.modname, dump, edit)
|
||||||
|
|
||||||
|
|
||||||
class BaseBackend(object):
|
class BaseBackend(object):
|
||||||
# Backend name.
|
# Backend name.
|
||||||
NAME = None
|
NAME = None
|
||||||
|
|
@ -149,7 +151,8 @@ class BaseBackend(object):
|
||||||
# NOT yet filled.
|
# NOT yet filled.
|
||||||
OBJECTS = {}
|
OBJECTS = {}
|
||||||
|
|
||||||
class ConfigError(Exception): pass
|
class ConfigError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
|
|
@ -184,6 +187,7 @@ class BaseBackend(object):
|
||||||
class classprop(object):
|
class classprop(object):
|
||||||
def __init__(self, fget):
|
def __init__(self, fget):
|
||||||
self.fget = fget
|
self.fget = fget
|
||||||
|
|
||||||
def __get__(self, inst, objtype=None):
|
def __get__(self, inst, objtype=None):
|
||||||
if inst:
|
if inst:
|
||||||
return self.fget(inst)
|
return self.fget(inst)
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -28,6 +28,7 @@ from weboob.tools.test import BackendTest
|
||||||
|
|
||||||
__all__ = ['GenericComicReaderBackend']
|
__all__ = ['GenericComicReaderBackend']
|
||||||
|
|
||||||
|
|
||||||
class DisplayPage(BasePage):
|
class DisplayPage(BasePage):
|
||||||
def get_page(self, gallery):
|
def get_page(self, gallery):
|
||||||
src = self.document.xpath(self.browser.params['img_src_xpath'])[0]
|
src = self.document.xpath(self.browser.params['img_src_xpath'])[0]
|
||||||
|
|
@ -102,7 +103,6 @@ class GenericComicReaderBackend(BaseBackend, ICapGallery):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
gallery = BaseGallery(_id, url=(self.ID_TO_URL % _id))
|
gallery = BaseGallery(_id, url=(self.ID_TO_URL % _id))
|
||||||
with self.browser:
|
with self.browser:
|
||||||
return gallery
|
return gallery
|
||||||
|
|
@ -116,7 +116,7 @@ class GenericComicReaderBackend(BaseBackend, ICapGallery):
|
||||||
|
|
||||||
OBJECTS = {
|
OBJECTS = {
|
||||||
BaseGallery: fill_gallery,
|
BaseGallery: fill_gallery,
|
||||||
BaseImage: fill_image }
|
BaseImage: fill_image}
|
||||||
|
|
||||||
|
|
||||||
class GenericComicReaderTest(BackendTest):
|
class GenericComicReaderTest(BackendTest):
|
||||||
|
|
@ -126,4 +126,3 @@ class GenericComicReaderTest(BackendTest):
|
||||||
it.next()
|
it.next()
|
||||||
img = it.next()
|
img = it.next()
|
||||||
self.backend.fillobj(img, ('url', 'data'))
|
self.backend.fillobj(img, ('url', 'data'))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,12 @@
|
||||||
# python2.5 compatibility
|
# python2.5 compatibility
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from weboob.capabilities.messages import ICapMessages, Message, Thread
|
from weboob.capabilities.messages import ICapMessages, Message, Thread
|
||||||
from weboob.tools.backend import BaseBackend
|
from weboob.tools.backend import BaseBackend
|
||||||
from weboob.tools.newsfeed import Newsfeed
|
from weboob.tools.newsfeed import Newsfeed
|
||||||
|
|
||||||
|
|
||||||
class GenericNewspaperBackend(BaseBackend, ICapMessages):
|
class GenericNewspaperBackend(BaseBackend, ICapMessages):
|
||||||
"GenericNewspaperBackend class"
|
"GenericNewspaperBackend class"
|
||||||
MAINTAINER = 'Julien Hebert'
|
MAINTAINER = 'Julien Hebert'
|
||||||
|
|
@ -71,13 +72,13 @@ class GenericNewspaperBackend(BaseBackend, ICapMessages):
|
||||||
content=content.body,
|
content=content.body,
|
||||||
signature='URL: %s' % content.url,
|
signature='URL: %s' % content.url,
|
||||||
flags=flags,
|
flags=flags,
|
||||||
children= [])
|
children=[])
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
def iter_threads(self):
|
def iter_threads(self):
|
||||||
for article in Newsfeed(self.RSS_FEED, GenericNewspaperBackend.RSSID).iter_entries():
|
for article in Newsfeed(self.RSS_FEED, GenericNewspaperBackend.RSSID).iter_entries():
|
||||||
thread = Thread(article.id)
|
thread = Thread(article.id)
|
||||||
thread.title = article.title
|
thread.title = article.title
|
||||||
thread.date = article.datetime
|
thread.date = article.datetime
|
||||||
yield(thread)
|
yield(thread)
|
||||||
|
|
||||||
|
|
@ -112,7 +113,7 @@ class GenericNewspaperBackend(BaseBackend, ICapMessages):
|
||||||
if time.time() - lastpurge > 7200:
|
if time.time() - lastpurge > 7200:
|
||||||
self.storage.set('lastpurge', time.time())
|
self.storage.set('lastpurge', time.time())
|
||||||
for id in self.storage.get('seen', default={}):
|
for id in self.storage.get('seen', default={}):
|
||||||
l.append((int(url2id(id)), id))
|
l.append((int(url2id(id)), id))
|
||||||
l.sort()
|
l.sort()
|
||||||
l.reverse()
|
l.reverse()
|
||||||
tosave = [v[1] for v in l[0:self.RSSSIZE + 10]]
|
tosave = [v[1] for v in l[0:self.RSSSIZE + 10]]
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ from lxml.etree import Comment
|
||||||
|
|
||||||
|
|
||||||
def try_remove(parser, base_element, selector):
|
def try_remove(parser, base_element, selector):
|
||||||
try :
|
try:
|
||||||
base_element.remove(parser.select(base_element, selector, 1 ))
|
base_element.remove(parser.select(base_element, selector, 1))
|
||||||
except (BrokenPageError, ValueError):
|
except (BrokenPageError, ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -33,6 +33,7 @@ def try_drop_tree(parser, base_element, selector):
|
||||||
for el in parser.select(base_element, selector):
|
for el in parser.select(base_element, selector):
|
||||||
el.drop_tree()
|
el.drop_tree()
|
||||||
|
|
||||||
|
|
||||||
def remove_from_selector_list(parser, base_element, selector_list):
|
def remove_from_selector_list(parser, base_element, selector_list):
|
||||||
for selector in selector_list:
|
for selector in selector_list:
|
||||||
base_element.remove(parser.select(base_element, selector, 1))
|
base_element.remove(parser.select(base_element, selector, 1))
|
||||||
|
|
@ -42,24 +43,28 @@ def try_remove_from_selector_list(parser, base_element, selector_list):
|
||||||
for selector in selector_list:
|
for selector in selector_list:
|
||||||
try_remove(parser, base_element, selector)
|
try_remove(parser, base_element, selector)
|
||||||
|
|
||||||
|
|
||||||
def drop_comments(base_element):
|
def drop_comments(base_element):
|
||||||
for comment in base_element.getiterator(Comment):
|
for comment in base_element.getiterator(Comment):
|
||||||
comment.drop_tree()
|
comment.drop_tree()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NoAuthorElement(BrokenPageError):
|
class NoAuthorElement(BrokenPageError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoBodyElement(BrokenPageError):
|
class NoBodyElement(BrokenPageError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoTitleException(BrokenPageError):
|
class NoTitleException(BrokenPageError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoneMainDiv(AttributeError):
|
class NoneMainDiv(AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Article(object):
|
class Article(object):
|
||||||
author = u''
|
author = u''
|
||||||
title = u''
|
title = u''
|
||||||
|
|
@ -71,10 +76,11 @@ class Article(object):
|
||||||
self.url = u''
|
self.url = u''
|
||||||
self.date = None
|
self.date = None
|
||||||
|
|
||||||
|
|
||||||
class GenericNewsPage(BasePage):
|
class GenericNewsPage(BasePage):
|
||||||
__element_body = NotImplementedError
|
__element_body = NotImplementedError
|
||||||
__article = Article
|
__article = Article
|
||||||
element_title_selector = NotImplementedError
|
element_title_selector = NotImplementedError
|
||||||
main_div = NotImplementedError
|
main_div = NotImplementedError
|
||||||
element_body_selector = NotImplementedError
|
element_body_selector = NotImplementedError
|
||||||
element_author_selector = NotImplementedError
|
element_author_selector = NotImplementedError
|
||||||
|
|
@ -90,7 +96,7 @@ class GenericNewsPage(BasePage):
|
||||||
return self.__article.author
|
return self.__article.author
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self):
|
||||||
try :
|
try:
|
||||||
return self.parser.select(
|
return self.parser.select(
|
||||||
self.main_div,
|
self.main_div,
|
||||||
self.element_title_selector,
|
self.element_title_selector,
|
||||||
|
|
@ -108,7 +114,7 @@ class GenericNewsPage(BasePage):
|
||||||
return self.get_title()
|
return self.get_title()
|
||||||
|
|
||||||
def get_element_body(self):
|
def get_element_body(self):
|
||||||
try :
|
try:
|
||||||
return self.parser.select(self.main_div, self.element_body_selector, 1)
|
return self.parser.select(self.main_div, self.element_body_selector, 1)
|
||||||
except BrokenPageError:
|
except BrokenPageError:
|
||||||
raise NoBodyElement("no body on %s" % (self.browser))
|
raise NoBodyElement("no body on %s" % (self.browser))
|
||||||
|
|
|
||||||
|
|
@ -21,87 +21,88 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import Image
|
import Image
|
||||||
|
|
||||||
|
|
||||||
class VirtKeyboardError(Exception):
|
class VirtKeyboardError(Exception):
|
||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
Exception.__init__(self, msg)
|
Exception.__init__(self, msg)
|
||||||
|
|
||||||
|
|
||||||
class VirtKeyboard(object):
|
class VirtKeyboard(object):
|
||||||
def __init__(self, file,coords,color):
|
def __init__(self, file, coords, color):
|
||||||
# file: virtual keyboard image
|
# file: virtual keyboard image
|
||||||
# coords: dictionary <value to return>:<tuple(x1,y1,x2,y2)>
|
# coords: dictionary <value to return>:<tuple(x1,y1,x2,y2)>
|
||||||
# color: color of the symbols in the image
|
# color: color of the symbols in the image
|
||||||
# depending on the image, it can be a single value or a tuple
|
# depending on the image, it can be a single value or a tuple
|
||||||
img=Image.open(file)
|
img = Image.open(file)
|
||||||
|
|
||||||
self.bands=img.getbands()
|
self.bands = img.getbands()
|
||||||
if isinstance(color,int) and not isinstance(self.bands,str) and len(self.bands)!=1:
|
if isinstance(color, int) and not isinstance(self.bands, str) and len(self.bands) != 1:
|
||||||
raise VirtKeyboardError("Color requires %i component but only 1 is provided" \
|
raise VirtKeyboardError("Color requires %i component but only 1 is provided" \
|
||||||
% len(self.bands))
|
% len(self.bands))
|
||||||
if not isinstance(color, int) and len(color)!=len(self.bands):
|
if not isinstance(color, int) and len(color) != len(self.bands):
|
||||||
raise VirtKeyboardError("Color requires %i components but %i are provided" \
|
raise VirtKeyboardError("Color requires %i components but %i are provided" \
|
||||||
% (len(self.bands),len(color)))
|
% (len(self.bands), len(color)))
|
||||||
self.color=color
|
self.color = color
|
||||||
|
|
||||||
(self.width,self.height)=img.size
|
(self.width, self.height) = img.size
|
||||||
self.pixar=img.load()
|
self.pixar = img.load()
|
||||||
self.coords={}
|
self.coords = {}
|
||||||
self.md5={}
|
self.md5 = {}
|
||||||
for i in coords.keys():
|
for i in coords.keys():
|
||||||
coord=self.get_symbol_coords(coords[i])
|
coord = self.get_symbol_coords(coords[i])
|
||||||
if coord==(-1,-1,-1,-1):
|
if coord == (-1, -1, -1, -1):
|
||||||
continue
|
continue
|
||||||
self.coords[i]=coord
|
self.coords[i] = coord
|
||||||
self.md5[i]=self.checksum(self.coords[i])
|
self.md5[i] = self.checksum(self.coords[i])
|
||||||
|
|
||||||
def get_symbol_coords(self,(x1,y1,x2,y2)):
|
def get_symbol_coords(self, (x1, y1, x2, y2)):
|
||||||
newY1=-1
|
newY1 = -1
|
||||||
newY2=-1
|
newY2 = -1
|
||||||
for y in range(y1,min(y2+1,self.height)):
|
for y in range(y1, min(y2 + 1, self.height)):
|
||||||
empty_line=True
|
empty_line = True
|
||||||
for x in range(x1,min(x2+1,self.width)):
|
for x in range(x1, min(x2 + 1, self.width)):
|
||||||
if self.pixar[x,y] == self.color:
|
if self.pixar[x, y] == self.color:
|
||||||
empty_line=False
|
empty_line = False
|
||||||
if newY1==-1:
|
if newY1 == -1:
|
||||||
newY1=y
|
newY1 = y
|
||||||
break;
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
if newY1!=-1 and not empty_line:
|
|
||||||
newY2=y
|
|
||||||
newX1=-1
|
|
||||||
newX2=-1
|
|
||||||
for x in range(x1,min(x2+1,self.width)):
|
|
||||||
empty_column=True
|
|
||||||
for y in range(y1,min(y2+1,self.height)):
|
|
||||||
if self.pixar[x,y] == self.color:
|
|
||||||
empty_column=False
|
|
||||||
if newX1==-1:
|
|
||||||
newX1=x
|
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
if newX1!=-1 and not empty_column:
|
if newY1 != -1 and not empty_line:
|
||||||
newX2=x
|
newY2 = y
|
||||||
return (newX1,newY1,newX2,newY2)
|
newX1 = -1
|
||||||
|
newX2 = -1
|
||||||
|
for x in range(x1, min(x2 + 1, self.width)):
|
||||||
|
empty_column = True
|
||||||
|
for y in range(y1, min(y2 + 1, self.height)):
|
||||||
|
if self.pixar[x, y] == self.color:
|
||||||
|
empty_column = False
|
||||||
|
if newX1 == -1:
|
||||||
|
newX1 = x
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if newX1 != -1 and not empty_column:
|
||||||
|
newX2 = x
|
||||||
|
return (newX1, newY1, newX2, newY2)
|
||||||
|
|
||||||
def checksum(self,(x1,y1,x2,y2)):
|
def checksum(self, (x1, y1, x2, y2)):
|
||||||
s = ''
|
s = ''
|
||||||
for y in range(y1,min(y2+1,self.height)):
|
for y in range(y1, min(y2 + 1, self.height)):
|
||||||
for x in range(x1,min(x2+1,self.width)):
|
for x in range(x1, min(x2 + 1, self.width)):
|
||||||
if self.pixar[x,y]==self.color:
|
if self.pixar[x, y] == self.color:
|
||||||
s += "."
|
s += "."
|
||||||
else:
|
else:
|
||||||
s += " "
|
s += " "
|
||||||
return hashlib.md5(s).hexdigest()
|
return hashlib.md5(s).hexdigest()
|
||||||
|
|
||||||
def get_symbol_code(self,md5sum):
|
def get_symbol_code(self, md5sum):
|
||||||
for i in self.md5.keys():
|
for i in self.md5.keys():
|
||||||
if md5sum == self.md5[i]:
|
if md5sum == self.md5[i]:
|
||||||
return i
|
return i
|
||||||
raise VirtKeyboardError('Symbol not found')
|
raise VirtKeyboardError('Symbol not found')
|
||||||
|
|
||||||
def check_symbols(self,symbols,dirname):
|
def check_symbols(self, symbols, dirname):
|
||||||
# symbols: dictionary <symbol>:<md5 value>
|
# symbols: dictionary <symbol>:<md5 value>
|
||||||
for s in symbols.keys():
|
for s in symbols.keys():
|
||||||
try:
|
try:
|
||||||
|
|
@ -109,32 +110,33 @@ class VirtKeyboard(object):
|
||||||
except VirtKeyboardError:
|
except VirtKeyboardError:
|
||||||
self.generate_MD5(dirname)
|
self.generate_MD5(dirname)
|
||||||
raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s"\
|
raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s"\
|
||||||
% (s,dirname))
|
% (s, dirname))
|
||||||
|
|
||||||
def generate_MD5(self,dir):
|
def generate_MD5(self, dir):
|
||||||
for i in self.coords.keys():
|
for i in self.coords.keys():
|
||||||
width=self.coords[i][2]-self.coords[i][0]+1
|
width = self.coords[i][2] - self.coords[i][0] + 1
|
||||||
height=self.coords[i][3]-self.coords[i][1]+1
|
height = self.coords[i][3] - self.coords[i][1] + 1
|
||||||
img=Image.new(''.join(self.bands),(width,height))
|
img = Image.new(''.join(self.bands), (width, height))
|
||||||
matrix=img.load()
|
matrix = img.load()
|
||||||
for y in range(height):
|
for y in range(height):
|
||||||
for x in range(width):
|
for x in range(width):
|
||||||
matrix[x,y]=self.pixar[self.coords[i][0]+x,self.coords[i][1]+y]
|
matrix[x, y] = self.pixar[self.coords[i][0] + x, self.coords[i][1] + y]
|
||||||
img.save(dir+"/"+self.md5[i]+".png")
|
img.save(dir + "/" + self.md5[i] + ".png")
|
||||||
|
|
||||||
|
|
||||||
class MappedVirtKeyboard(VirtKeyboard):
|
class MappedVirtKeyboard(VirtKeyboard):
|
||||||
def __init__(self, file, document, img_element, color, map_attr="onclick"):
|
def __init__(self, file, document, img_element, color, map_attr="onclick"):
|
||||||
map_id=img_element.attrib.get("usemap")[1:]
|
map_id = img_element.attrib.get("usemap")[1:]
|
||||||
map=document.find("//map[@id='"+map_id+"']")
|
map = document.find("//map[@id='" + map_id + "']")
|
||||||
if map is None:
|
if map is None:
|
||||||
map=document.find("//map[@name='"+map_id+"']")
|
map = document.find("//map[@name='" + map_id + "']")
|
||||||
|
|
||||||
coords={}
|
coords = {}
|
||||||
for area in map.getiterator("area"):
|
for area in map.getiterator("area"):
|
||||||
code=area.attrib.get(map_attr)
|
code = area.attrib.get(map_attr)
|
||||||
area_coords=[]
|
area_coords = []
|
||||||
for coord in area.attrib.get("coords").split(','):
|
for coord in area.attrib.get("coords").split(','):
|
||||||
area_coords.append(int(coord))
|
area_coords.append(int(coord))
|
||||||
coords[code]=tuple(area_coords)
|
coords[code] = tuple(area_coords)
|
||||||
|
|
||||||
VirtKeyboard.__init__(self,file,coords,color)
|
VirtKeyboard.__init__(self, file, coords, color)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class ConfigError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IConfig:
|
class IConfig(object):
|
||||||
def load(self, default={}):
|
def load(self, default={}):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,12 @@ def retry(ExceptionToCheck, tries=4, delay=3, backoff=2):
|
||||||
try_one_last_time = False
|
try_one_last_time = False
|
||||||
break
|
break
|
||||||
except ExceptionToCheck, e:
|
except ExceptionToCheck, e:
|
||||||
logging.debug(u'%s, Retrying in %d seconds...' % (e,
|
logging.debug(u'%s, Retrying in %d seconds...' % (e, mdelay))
|
||||||
mdelay))
|
|
||||||
time.sleep(mdelay)
|
time.sleep(mdelay)
|
||||||
mtries -= 1
|
mtries -= 1
|
||||||
mdelay *= backoff
|
mdelay *= backoff
|
||||||
if try_one_last_time:
|
if try_one_last_time:
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
return
|
return
|
||||||
return f_retry # true decorator
|
return f_retry # true decorator
|
||||||
return deco_retry
|
return deco_retry
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,13 @@ COLORS = {
|
||||||
'CRITICAL': COLOR_SEQ % ("\033[1;33m\033[1;41m"),
|
'CRITICAL': COLOR_SEQ % ("\033[1;33m\033[1;41m"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def getLogger(name, parent=None):
|
def getLogger(name, parent=None):
|
||||||
if parent:
|
if parent:
|
||||||
name = parent.name + '.' + name
|
name = parent.name + '.' + name
|
||||||
return _getLogger(name)
|
return _getLogger(name)
|
||||||
|
|
||||||
|
|
||||||
class ColoredFormatter(Formatter):
|
class ColoredFormatter(Formatter):
|
||||||
"""
|
"""
|
||||||
Class written by airmind:
|
Class written by airmind:
|
||||||
|
|
@ -52,9 +54,9 @@ class ColoredFormatter(Formatter):
|
||||||
msg = COLORS[levelname] % msg
|
msg = COLORS[levelname] % msg
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
def createColoredFormatter(stream, format):
|
def createColoredFormatter(stream, format):
|
||||||
if (sys.platform != 'win32') and stream.isatty():
|
if (sys.platform != 'win32') and stream.isatty():
|
||||||
return ColoredFormatter(format)
|
return ColoredFormatter(format)
|
||||||
else:
|
else:
|
||||||
return Formatter(format)
|
return Formatter(format)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ try:
|
||||||
html2text = h2t.html2text
|
html2text = h2t.html2text
|
||||||
except ImportError:
|
except ImportError:
|
||||||
warning('python-html2text is not present. HTML pages will not be converted into text.')
|
warning('python-html2text is not present. HTML pages will not be converted into text.')
|
||||||
|
|
||||||
def html2text(html):
|
def html2text(html):
|
||||||
return html
|
return html
|
||||||
|
|
||||||
|
|
@ -117,6 +118,7 @@ def utc2local(date):
|
||||||
date = date.astimezone(tz.tzlocal())
|
date = date.astimezone(tz.tzlocal())
|
||||||
return date
|
return date
|
||||||
|
|
||||||
|
|
||||||
def limit(iterator, lim):
|
def limit(iterator, lim):
|
||||||
count = 0
|
count = 0
|
||||||
iterator = iter(iterator)
|
iterator = iter(iterator)
|
||||||
|
|
@ -125,6 +127,7 @@ def limit(iterator, lim):
|
||||||
count += 1
|
count += 1
|
||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
|
|
||||||
|
|
||||||
def ratelimit(group, delay):
|
def ratelimit(group, delay):
|
||||||
"""
|
"""
|
||||||
Simple rate limiting.
|
Simple rate limiting.
|
||||||
|
|
|
||||||
|
|
@ -29,46 +29,46 @@ if feedparser.__version__ >= '5.0':
|
||||||
__all__ = ['Entry', 'Newsfeed']
|
__all__ = ['Entry', 'Newsfeed']
|
||||||
|
|
||||||
|
|
||||||
class Entry:
|
class Entry(object):
|
||||||
def __init__(self, entry, rssid_func=None):
|
def __init__(self, entry, rssid_func=None):
|
||||||
if hasattr(entry, 'id'):
|
if hasattr(entry, 'id'):
|
||||||
self.id = entry.id
|
self.id = entry.id
|
||||||
else:
|
else:
|
||||||
self.id = None
|
self.id = None
|
||||||
|
|
||||||
if entry.has_key("link"):
|
if "link" in entry:
|
||||||
self.link = entry["link"]
|
self.link = entry["link"]
|
||||||
else:
|
else:
|
||||||
self.link = None
|
self.link = None
|
||||||
|
|
||||||
if entry.has_key("title"):
|
if "title" in entry:
|
||||||
self.title = entry["title"]
|
self.title = entry["title"]
|
||||||
else:
|
else:
|
||||||
self.title = None
|
self.title = None
|
||||||
|
|
||||||
if entry.has_key("author"):
|
if "author" in entry:
|
||||||
self.author = entry["author"]
|
self.author = entry["author"]
|
||||||
else:
|
else:
|
||||||
self.author = None
|
self.author = None
|
||||||
|
|
||||||
if entry.has_key("updated_parsed"):
|
if "updated_parsed" in entry:
|
||||||
self.datetime = datetime.datetime(*entry['updated_parsed'][:7])
|
self.datetime = datetime.datetime(*entry['updated_parsed'][:7])
|
||||||
else:
|
else:
|
||||||
self.datetime = None
|
self.datetime = None
|
||||||
|
|
||||||
if entry.has_key("summary"):
|
if "summary" in entry:
|
||||||
self.summary = entry["summary"]
|
self.summary = entry["summary"]
|
||||||
else:
|
else:
|
||||||
self.summary = None
|
self.summary = None
|
||||||
|
|
||||||
self.content = []
|
self.content = []
|
||||||
if entry.has_key("content"):
|
if "content" in entry:
|
||||||
for i in entry["content"]:
|
for i in entry["content"]:
|
||||||
self.content.append(i.value)
|
self.content.append(i.value)
|
||||||
elif self.summary:
|
elif self.summary:
|
||||||
self.content.append(self.summary)
|
self.content.append(self.summary)
|
||||||
|
|
||||||
if entry.has_key("wfw_commentrss"):
|
if "wfw_commentrss" in entry:
|
||||||
self.rsscomment = entry["wfw_commentrss"]
|
self.rsscomment = entry["wfw_commentrss"]
|
||||||
else:
|
else:
|
||||||
self.rsscomment = None
|
self.rsscomment = None
|
||||||
|
|
@ -76,7 +76,8 @@ class Entry:
|
||||||
if rssid_func:
|
if rssid_func:
|
||||||
self.id = rssid_func(self)
|
self.id = rssid_func(self)
|
||||||
|
|
||||||
class Newsfeed:
|
|
||||||
|
class Newsfeed(object):
|
||||||
def __init__(self, url, rssid_func=None):
|
def __init__(self, url, rssid_func=None):
|
||||||
self.feed = feedparser.parse(url)
|
self.feed = feedparser.parse(url)
|
||||||
self.rssid_func = rssid_func
|
self.rssid_func = rssid_func
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ except ImportError:
|
||||||
## {{{ http://code.activestate.com/recipes/576693/ (r6)
|
## {{{ http://code.activestate.com/recipes/576693/ (r6)
|
||||||
from UserDict import DictMixin
|
from UserDict import DictMixin
|
||||||
|
|
||||||
|
|
||||||
class OrderedDict(dict, DictMixin):
|
class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
def __init__(self, *args, **kwds):
|
def __init__(self, *args, **kwds):
|
||||||
|
|
|
||||||
|
|
@ -24,34 +24,42 @@ import logging
|
||||||
__all__ = ['get_parser', 'NoParserFound']
|
__all__ = ['get_parser', 'NoParserFound']
|
||||||
|
|
||||||
|
|
||||||
class NoParserFound(Exception): pass
|
class NoParserFound(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def load_lxml():
|
def load_lxml():
|
||||||
from .lxmlparser import LxmlHtmlParser
|
from .lxmlparser import LxmlHtmlParser
|
||||||
return LxmlHtmlParser
|
return LxmlHtmlParser
|
||||||
|
|
||||||
|
|
||||||
def load_lxmlsoup():
|
def load_lxmlsoup():
|
||||||
from .lxmlsoupparser import LxmlSoupParser
|
from .lxmlsoupparser import LxmlSoupParser
|
||||||
return LxmlSoupParser
|
return LxmlSoupParser
|
||||||
|
|
||||||
|
|
||||||
def load_html5lib():
|
def load_html5lib():
|
||||||
from .html5libparser import Html5libParser
|
from .html5libparser import Html5libParser
|
||||||
return Html5libParser
|
return Html5libParser
|
||||||
|
|
||||||
|
|
||||||
def load_elementtidy():
|
def load_elementtidy():
|
||||||
from .elementtidyparser import ElementTidyParser
|
from .elementtidyparser import ElementTidyParser
|
||||||
return ElementTidyParser
|
return ElementTidyParser
|
||||||
|
|
||||||
|
|
||||||
def load_builtin():
|
def load_builtin():
|
||||||
from .htmlparser import HTMLParser
|
from .htmlparser import HTMLParser
|
||||||
return HTMLParser
|
return HTMLParser
|
||||||
|
|
||||||
|
|
||||||
def load_json():
|
def load_json():
|
||||||
# This parser doesn't read HTML, don't include it in the
|
# This parser doesn't read HTML, don't include it in the
|
||||||
# preference_order default value below.
|
# preference_order default value below.
|
||||||
from .jsonparser import JsonParser
|
from .jsonparser import JsonParser
|
||||||
return JsonParser
|
return JsonParser
|
||||||
|
|
||||||
|
|
||||||
def get_parser(preference_order=('lxml', 'lxmlsoup')):
|
def get_parser(preference_order=('lxml', 'lxmlsoup')):
|
||||||
"""
|
"""
|
||||||
Get a parser from a preference order list.
|
Get a parser from a preference order list.
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ class Html5libParser(HTMLParser, IParser):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Default implementation for each type of API.
|
# Default implementation for each type of API.
|
||||||
defaults = {'etree': ElementTree,
|
defaults = {'etree': ElementTree}
|
||||||
}
|
|
||||||
def __init__(self, api='etree'):
|
def __init__(self, api='etree'):
|
||||||
# if no default implementation is defined for this api, set it to None
|
# if no default implementation is defined for this api, set it to None
|
||||||
# to let getTreeBuilder() using the corresponding implementation.
|
# to let getTreeBuilder() using the corresponding implementation.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# For Python 2.5-, this will enable the simliar property mechanism as in
|
# For Python 2.5-, this will enable the similar property mechanism as in
|
||||||
# Python 2.6+/3.0+. The code is based on
|
# Python 2.6+/3.0+. The code is based on
|
||||||
# http://bruynooghe.blogspot.com/2008/04/xsetter-syntax-in-python-25.html
|
# http://bruynooghe.blogspot.com/2008/04/xsetter-syntax-in-python-25.html
|
||||||
|
|
||||||
|
|
@ -27,26 +27,26 @@ import __builtin__
|
||||||
|
|
||||||
|
|
||||||
class property(property):
|
class property(property):
|
||||||
def __init__(self, fget, *args, **kwargs):
|
def __init__(self, fget, *args, **kwargs):
|
||||||
self.__doc__ = fget.__doc__
|
self.__doc__ = fget.__doc__
|
||||||
super(property, self).__init__(fget, *args, **kwargs)
|
super(property, self).__init__(fget, *args, **kwargs)
|
||||||
|
|
||||||
def setter(self, fset):
|
def setter(self, fset):
|
||||||
cls_ns = sys._getframe(1).f_locals
|
cls_ns = sys._getframe(1).f_locals
|
||||||
for k, v in cls_ns.iteritems():
|
for k, v in cls_ns.iteritems():
|
||||||
if v == self:
|
if v == self:
|
||||||
propname = k
|
propname = k
|
||||||
break
|
break
|
||||||
cls_ns[propname] = property(self.fget, fset, self.fdel, self.__doc__)
|
cls_ns[propname] = property(self.fget, fset, self.fdel, self.__doc__)
|
||||||
return cls_ns[propname]
|
return cls_ns[propname]
|
||||||
|
|
||||||
def deleter(self, fdel):
|
def deleter(self, fdel):
|
||||||
cls_ns = sys._getframe(1).f_locals
|
cls_ns = sys._getframe(1).f_locals
|
||||||
for k, v in cls_ns.iteritems():
|
for k, v in cls_ns.iteritems():
|
||||||
if v == self:
|
if v == self:
|
||||||
propname = k
|
propname = k
|
||||||
break
|
break
|
||||||
cls_ns[propname] = property(self.fget, self.fset, fdel, self.__doc__)
|
cls_ns[propname] = property(self.fget, self.fset, fdel, self.__doc__)
|
||||||
return cls_ns[propname]
|
return cls_ns[propname]
|
||||||
|
|
||||||
__builtin__.property = property
|
__builtin__.property = property
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ from copy import deepcopy
|
||||||
from .config.yamlconfig import YamlConfig
|
from .config.yamlconfig import YamlConfig
|
||||||
|
|
||||||
|
|
||||||
class IStorage:
|
class IStorage(object):
|
||||||
def load(self, what, name, default={}):
|
def load(self, what, name, default={}):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue