pax_global_header 0000666 0000000 0000000 00000000064 13507732170 0014517 g ustar 00root root 0000000 0000000 52 comment=ef0182519846a82abb51539df07730e9e01be395
woob-ef0182519846a82abb51539df07730e9e01be395-tools/ 0000775 0000000 0000000 00000000000 13507732170 0020411 5 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/ 0000775 0000000 0000000 00000000000 13507732170 0021551 5 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/ 0000775 0000000 0000000 00000000000 13507732170 0024053 5 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/__init__.py 0000664 0000000 0000000 00000000000 13507732170 0026152 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate.py 0000775 0000000 0000000 00000004375 13507732170 0026743 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2013-2019 Laurent Bachelier, Sébastien Jean
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with weboob. If not, see .
from __future__ import print_function
import argparse
import os
import subprocess
import sys
from importlib import import_module
BOILERPLATE_PATH = os.getenv(
'BOILERPLATE_PATH',
os.path.realpath(os.path.join(os.path.dirname(__file__), 'boilerplate_data')))
sys.path.append(os.path.dirname(__file__))
sys.path.append(BOILERPLATE_PATH)
from recipe import Recipe # NOQA
def u8(s):
if isinstance(s, bytes):
return s.decode('utf-8')
return s
def gitconfig(entry):
return u8(subprocess.check_output('git config -z --get %s' % entry, shell=True)[:-1])
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'-a', '--author',
default=gitconfig('user.name'), type=u8)
parser.add_argument(
'-e', '--email',
default=gitconfig('user.email'), type=u8)
subparsers = parser.add_subparsers(dest='recipe')
subparsers.required = True
recipes_module = import_module('recipes', package='boilerplate_data')
if hasattr(recipes_module, '__all__'):
for k in recipes_module.__all__:
getattr(recipes_module, k).configure_subparser(subparsers)
else:
for k in dir(recipes_module):
print(k)
if issubclass(getattr(recipes_module, k), Recipe) and not k.startswith('_'):
getattr(recipes_module, k).configure_subparser(subparsers)
args = parser.parse_args()
recipe = args.recipe_class(args)
recipe.generate()
if __name__ == '__main__':
main()
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data/ 0000775 0000000 0000000 00000000000 13507732170 0027346 5 ustar 00root root 0000000 0000000 base_browser.pyt 0000664 0000000 0000000 00000001173 13507732170 0032504 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data <%inherit file="layout.pyt"/>
from weboob.browser import ${'LoginBrowser, need_login' if r.login else 'PagesBrowser'}, URL
from .pages import Page1, Page2
class ${r.classname}Browser(${'Login' if r.login else 'Pages'}Browser):
BASEURL = 'http://www.${r.name}.com'
page1 = URL('/page1\?id=(?P.+)', Page1)
page2 = URL('/page2', Page2)
% if login:
def do_login(self):
pass
@need_login
% endif
def get_stuff(self, _id):
self.page1.go(id=_id)
assert self.page1.is_here()
self.page.do_stuff(_id)
assert self.page2.is_here()
return self.page.do_more_stuff()
base_module.pyt 0000664 0000000 0000000 00000000613 13507732170 0032304 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data <%inherit file="layout.pyt"/>
from weboob.tools.backend import Module
from .browser import ${r.classname}Browser
__all__ = ['${r.classname}Module']
class ${r.classname}Module(Module):
NAME = '${r.name}'
DESCRIPTION = '${r.name} website'
MAINTAINER = '${r.author}'
EMAIL = '${r.email}'
LICENSE = 'LGPLv3+'
VERSION = '${r.version}'
BROWSER = ${r.classname}Browser
base_pages.pyt 0000664 0000000 0000000 00000000374 13507732170 0032122 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data <%inherit file="layout.pyt"/>
from weboob.browser.pages import HTMLPage
class Page1(HTMLPage):
def do_stuff(self, _id):
raise NotImplementedError()
class Page2(HTMLPage):
def do_more_stuff(self):
raise NotImplementedError()
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data/base_test.pyt0000664 0000000 0000000 00000000212 13507732170 0032050 0 ustar 00root root 0000000 0000000 <%inherit file="layout.pyt"/>
from weboob.tools.test import BackendTest
class ${r.classname}Test(BackendTest):
MODULE = '${r.name}'
cap_module.pyt 0000664 0000000 0000000 00000001626 13507732170 0032142 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data <%inherit file="layout.pyt"/>
from weboob.tools.backend import Module${', BackendConfig' if r.login else ''}
% if login:
from weboob.tools.value import Value, ValueBackendPassword
% endif
from ${r.capmodulename} import ${r.capname}
from .browser import ${r.classname}Browser
__all__ = ['${r.classname}Module']
class ${r.classname}Module(Module, ${r.capname}):
NAME = '${r.name}'
DESCRIPTION = '${r.name} website'
MAINTAINER = '${r.author}'
EMAIL = '${r.email}'
LICENSE = 'LGPLv3+'
VERSION = '${r.version}'
BROWSER = ${r.classname}Browser
% if login:
CONFIG = BackendConfig(
Value('username', help='Username'),
ValueBackendPassword('password', help='Password'),
)
def create_default_browser(self):
return self.create_browser(self.config['username'].get(), self.config['password'].get())
% endif
% for meth in r.methods:
${''.join(meth)}
% endfor
comic_module.pyt 0000664 0000000 0000000 00000001400 13507732170 0032457 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data <%inherit file="layout.pyt"/>
from weboob.tools.capabilities.gallery.genericcomicreader import GenericComicReaderModule, DisplayPage
__all__ = ['${r.classname}Module']
class ${r.classname}Module(GenericComicReaderModule):
NAME = '${r.name}'
DESCRIPTION = u'${r.name} manga reading site'
MAINTAINER = u'${r.author}'
EMAIL = '${r.email}'
VERSION = '${r.version}'
LICENSE = 'LGPLv3+'
DOMAIN = 'www.${r.name}.com'
BROWSER_PARAMS = dict(
img_src_xpath="//img[@id='comic_page']/@src",
page_list_xpath="(//select[@id='page_select'])[1]/option/@value")
ID_REGEXP = r'[^/]+/[^/]+'
URL_REGEXP = r'.+${r.name}.com/(%s).+' % ID_REGEXP
ID_TO_URL = 'http://www.${r.name}.com/%s'
PAGES = {URL_REGEXP: DisplayPage}
comic_test.pyt 0000664 0000000 0000000 00000000443 13507732170 0032157 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data <%inherit file="layout.pyt"/>
from weboob.tools.capabilities.gallery.genericcomicreadertest import GenericComicReaderTest
class ${r.classname}BackendTest(GenericComicReaderTest):
MODULE = '${r.name}'
def test_download(self):
return self._test_download('${r.download_id}')
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data/init.pyt 0000664 0000000 0000000 00000000154 13507732170 0031047 0 ustar 00root root 0000000 0000000 <%inherit file="layout.pyt"/>
from .module import ${r.classname}Module
__all__ = ['${r.classname}Module']
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data/layout.pyt 0000664 0000000 0000000 00000001472 13507732170 0031425 0 ustar 00root root 0000000 0000000 ${coding}
# Copyright(C) ${r.year} ${r.author}
#
# This file is part of a weboob module.
#
# This weboob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This weboob module is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see .
from __future__ import unicode_literals
${self.body()}\
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/boilerplate_data/recipes.py 0000664 0000000 0000000 00000011127 13507732170 0031354 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2013-2019 Laurent Bachelier, Sébastien Jean
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with weboob. If not, see .
from __future__ import print_function
import importlib
import sys
from recipe import Recipe
__all__ = ['BaseRecipe', 'CapRecipe', 'ComicRecipe', 'ComicTestRecipe']
class BaseRecipe(Recipe):
NAME = 'base'
def generate(self):
self.write('__init__.py', self.template('init'))
self.write('module.py', self.template('base_module'))
self.write('browser.py', self.template('base_browser'))
self.write('pages.py', self.template('base_pages'))
self.write('test.py', self.template('base_test'))
class CapRecipe(Recipe):
NAME = 'cap'
def __init__(self, args):
super(CapRecipe, self).__init__(args)
self.capname = args.capname
self.login = args.login
@classmethod
def configure_subparser(cls, subparsers):
subparser = super(CapRecipe, cls).configure_subparser(subparsers)
subparser.add_argument('--login', action='store_true', help='The site requires login')
subparser.add_argument('capname', help='Capability name')
return subparser
def find_module_cap(self):
if '.' not in self.capname:
return self.search_cap()
PREFIX = 'weboob.capabilities.'
if not self.capname.startswith(PREFIX):
self.capname = PREFIX + self.capname
try:
self.capmodulename, self.capname = self.capname.rsplit('.', 1)
except ValueError:
self.error('Cap name must be in format module.CapSomething or CapSomething')
try:
module = importlib.import_module(self.capmodulename)
except ImportError:
self.error('Module %r not found' % self.capmodulename)
try:
cap = getattr(module, self.capname)
except AttributeError:
self.error('Module %r has no such capability %r' % (self.capmodulename, self.capname))
return cap
def search_cap(self):
import pkgutil
import weboob.capabilities
modules = pkgutil.walk_packages(weboob.capabilities.__path__, prefix='weboob.capabilities.')
for _, capmodulename, __ in modules:
module = importlib.import_module(capmodulename)
if hasattr(module, self.capname):
self.capmodulename = capmodulename
return getattr(module, self.capname)
self.error('Capability %r not found' % self.capname)
def error(self, message):
print(message, file=sys.stderr)
sys.exit(1)
def methods_code(self, klass):
import inspect
methods = []
for name, member in inspect.getmembers(klass):
if inspect.ismethod(member) and name in klass.__dict__:
lines, _ = inspect.getsourcelines(member)
methods.append(lines)
return methods
def generate(self):
cap = self.find_module_cap()
self.methods = self.methods_code(cap)
self.write('__init__.py', self.template('init'))
self.write('module.py', self.template('cap_module'))
self.write('browser.py', self.template('base_browser'))
self.write('pages.py', self.template('base_pages'))
self.write('test.py', self.template('base_test'))
class ComicRecipe(Recipe):
NAME = 'comic'
def generate(self):
self.write('__init__.py', self.template('init'))
self.write('module.py', self.template('comic_module'))
class ComicTestRecipe(Recipe):
NAME = 'comic.test'
@classmethod
def configure_subparser(cls, subparsers):
subparser = super(ComicTestRecipe, cls).configure_subparser(subparsers)
subparser.add_argument('download_id', help='Download ID')
return subparser
def __init__(self, args):
super(ComicTestRecipe, self).__init__(args)
self.download_id = args.download_id
def generate(self):
self.write('test.py', self.template('comic_test'))
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/boilerplate/recipe.py 0000664 0000000 0000000 00000005353 13507732170 0025702 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2013-2019 Laurent Bachelier, Sébastien Jean
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with weboob. If not, see .
from __future__ import print_function
import codecs
import datetime
import os
import sys
from mako.lookup import TemplateLookup
from weboob import __version__
WEBOOB_MODULES = os.getenv(
'WEBOOB_MODULES',
os.path.realpath(os.path.join(os.path.dirname(__file__), '../../modules')))
BOILERPLATE_PATH = os.getenv(
'BOILERPLATE_PATH',
os.path.realpath(os.path.join(os.path.dirname(__file__), 'boilerplate_data')))
TEMPLATES = TemplateLookup(directories=[BOILERPLATE_PATH], input_encoding='utf-8')
def write(target, contents):
if not os.path.isdir(os.path.dirname(target)):
os.makedirs(os.path.dirname(target))
if os.path.exists(target):
print("%s already exists." % target, file=sys.stderr)
sys.exit(4)
with codecs.open(target, mode='w', encoding='utf-8') as f:
f.write(contents)
print('Created %s' % target)
class Recipe(object):
@classmethod
def configure_subparser(cls, subparsers):
subparser = subparsers.add_parser(cls.NAME)
subparser.add_argument('name', help='Module name')
subparser.set_defaults(recipe_class=cls)
return subparser
def __init__(self, args):
self.name = args.name.lower().replace(' ', '')
self.classname = args.name.title().replace(' ', '')
self.year = datetime.date.today().year
self.author = args.author
self.email = args.email
self.version = __version__
self.login = False
def write(self, filename, contents):
return write(os.path.join(WEBOOB_MODULES, self.name, filename), contents)
def template(self, name, **kwargs):
if '.' not in name:
name += '.pyt'
return TEMPLATES.get_template(name) \
.render(r=self,
# workaround, as it's also a mako directive
coding='# -*- coding: utf-8 -*-',
login=self.login,
**kwargs)
def generate(self):
raise NotImplementedError()
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/check_xpath.py 0000775 0000000 0000000 00000011402 13507732170 0024405 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# Copyright(C) 2017 Vincent A
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with weboob. If not, see .
from __future__ import print_function
import ast
import fnmatch
import os
import traceback
import lxml.etree
from weboob.browser.filters import standard
class Error(SyntaxError):
def __init__(self, file, line, message):
super(Error, self).__init__('%s:%s: %s' % (file, line, message))
self.file = file
self.line = line
def do_visits(*funcs):
def wrapper(self, node):
for func in funcs:
func(self, node)
self.generic_visit(node)
return wrapper
class Visitor(ast.NodeVisitor):
def __init__(self, file, *args, **kwargs):
self.warnings = kwargs.pop('warnings', False)
super(Visitor, self).__init__(*args, **kwargs)
self.file = file
self.filters = []
self.filters.extend(f for f in dir(standard) if isinstance(getattr(standard, f), type) and issubclass(getattr(standard, f), standard.CleanText))
self.filters.extend(['Regexp', 'XPath', 'Attr', 'Link'])
self.element_context = []
def check_xpath(self, s, lineno):
try:
lxml.etree.XPath(s)
except lxml.etree.XPathSyntaxError as exc:
raise Error(self.file, lineno, exc)
if self.warnings:
if not s.lstrip('(').startswith('.') and len(self.element_context) >= 2:
if self.element_context[-1] == 'ItemElement' and self.element_context[-2] in ('TableElement', 'ListElement'):
print('%s:%s: probable missing "." at start of XPath' % (self.file, lineno))
def _item_xpath(self, node):
try:
target, = node.targets
except ValueError:
return
if not isinstance(target, ast.Name) or target.id != 'item_xpath':
return
try:
if self.element_context[-1] not in ('TableElement', 'ListElement'):
return
except IndexError:
return
if not isinstance(node.value, ast.Str):
return
self.check_xpath(node.value.s, node.lineno)
visit_Assign = do_visits(_item_xpath)
def _xpath_call(self, node):
if not isinstance(node.func, ast.Attribute):
return
if node.func.attr != 'xpath':
return
try:
if not isinstance(node.args[0], ast.Str):
return
except IndexError:
return
self.check_xpath(node.args[0].s, node.lineno)
def _filter_call(self, node):
if not isinstance(node.func, ast.Name):
return
if node.func.id not in self.filters:
return
try:
if not isinstance(node.args[0], ast.Str):
return
except IndexError:
return
self.check_xpath(node.args[0].s, node.lineno)
visit_Call = do_visits(_xpath_call, _filter_call)
def visit_ClassDef(self, node):
has_element = False
for basenode in node.bases:
if isinstance(basenode, ast.Name) and basenode.id in ('ListElement', 'ItemElement', 'TableElement'):
self.element_context.append(basenode.id)
has_element = True
break
self.generic_visit(node)
if has_element:
self.element_context.pop()
def search_py(root):
for path, dirs, files in os.walk(root):
dirs.sort()
for f in fnmatch.filter(files, '*.py'):
yield os.path.join(path, f)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description="Check XPath definitions")
parser.add_argument('-w', '--warnings', action='store_true')
args = parser.parse_args()
modpath = os.getenv('WEBOOB_MODULES', os.path.normpath(os.path.dirname(__file__) + '/../modules'))
for fn in search_py(modpath):
with open(fn) as fd:
try:
node = ast.parse(fd.read(), fn)
except SyntaxError as exc:
print('In file', fn)
traceback.print_exc(exc)
try:
Visitor(fn, warnings=args.warnings).visit(node)
except SyntaxError as exc:
print(exc)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/common.sh 0000664 0000000 0000000 00000001371 13507732170 0023377 0 ustar 00root root 0000000 0000000 VER=2
if [ "${1-}" = "-3" ]; then
VER=3
shift
fi
if [ -z "${PYTHON2-}" ]; then
which python2.7 >/dev/null 2>&1 && PYTHON2=$(which python2.7)
which python2 >/dev/null 2>&1 && PYTHON2=$(which python2)
fi
if [ -z "${PYTHON3-}" ]; then
which python3.4 >/dev/null 2>&1 && PYTHON3=$(which python3.4)
which python3.5 >/dev/null 2>&1 && PYTHON3=$(which python3.5)
which python3.6 >/dev/null 2>&1 && PYTHON3=$(which python3.6)
which python3 >/dev/null 2>&1 && PYTHON3=$(which python3)
fi
if [ -z "${PYTHON-}" ]; then
which python >/dev/null 2>&1 && PYTHON=$(which python)
if [ $VER -eq 2 -a -n "${PYTHON2}" ]; then
PYTHON=${PYTHON2}
elif [ $VER -eq 3 -a -n "${PYTHON3}" ]; then
PYTHON=${PYTHON3}
fi
fi
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/debpydep.py 0000775 0000000 0000000 00000002431 13507732170 0023722 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import subprocess
import sys
selection = set()
dependencies = set()
for root, dirs, files in os.walk(sys.argv[1]):
for f in files:
if f.endswith('.py') and f != '__init__.py':
s = "from %s import %s" % (root.strip('/').replace('/', '.'), f[:-3])
try:
exec(s)
except ImportError as e:
print(str(e), file=sys.stderr)
else:
m = eval(f[:-3])
for attrname in dir(m):
try:
attr = getattr(m, attrname)
selection.add(attr.__file__)
except AttributeError:
pass
for f in selection:
f = f.replace('.pyc', '.py')
try:
f = os.path.abspath(os.path.join(os.path.split(f)[0], os.readlink(f)))
except OSError:
pass
p = subprocess.Popen(['/usr/bin/dpkg', '-S', f], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if p.wait() == 0:
for line in p.stdout.readlines():
line = line.decode('utf-8')
dependencies.add(line.strip().split(':')[0])
else:
print('not found: %s' % f)
for d in dependencies:
print(d)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/local_install.py 0000664 0000000 0000000 00000002435 13507732170 0024747 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import subprocess
import sys
print("Weboob local installer")
print()
if len(sys.argv) < 2:
print("This tool will install Weboob to be usuable without requiring")
print("messing with your system, which should only be touched by a package manager.")
print()
print("Usage: %s DESTINATION" % sys.argv[0])
print()
print("Error: Please provide a destination, "
"for example ‘%s/bin’" % os.getenv('HOME'), file=sys.stderr)
sys.exit(1)
else:
dest = os.path.expanduser(sys.argv[1])
print("Installing weboob applications into ‘%s’." % dest)
subprocess.check_call(
[sys.executable, 'setup.py',
'install', '--user', '--install-scripts=%s' % dest] + sys.argv[2:],
cwd=os.path.join(os.path.dirname(__file__), os.pardir))
subprocess.check_call([sys.executable, os.path.join(dest, 'weboob-config'), 'update'])
print()
print("Installation done. Applications are available in ‘%s’." % dest)
print("You can remove the source files.")
print()
print("To have easy access to the Weboob applications,")
print("you should add the following line to your ~/.bashrc or ~/.zshrc file:")
print("export PATH=\"$PATH:%s\"" % dest)
print("And then restart your shells.")
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/local_install.sh 0000775 0000000 0000000 00000000210 13507732170 0024721 0 ustar 00root root 0000000 0000000 #!/bin/sh
set -e
. "$(dirname $0)/common.sh"
$PYTHON "$(dirname $0)/stale_pyc.py"
exec $PYTHON "$(dirname $0)/local_install.py" "$@"
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/local_run.py 0000664 0000000 0000000 00000003440 13507732170 0024102 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import subprocess
import sys
if len(sys.argv) < 2:
print("Usage: %s SCRIPTNAME [args]" % sys.argv[0])
sys.exit(1)
else:
args = sys.argv[1:]
pyargs = []
while args and args[0].startswith('-'):
pyargs.append(args.pop(0))
script = args.pop(0)
project = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
wd = os.path.join(project, 'localconfig')
if not os.path.isdir(wd):
os.makedirs(wd)
paths = os.getenv('PYTHONPATH', None)
if not paths:
paths = sys.path
else:
paths = paths.split(':')
if project not in paths:
paths.insert(0, project)
env = os.environ.copy()
env['PYTHONPATH'] = ':'.join(p for p in paths if p)
env['WEBOOB_WORKDIR'] = wd
env['WEBOOB_DATADIR'] = wd
env['WEBOOB_BACKENDS'] = os.getenv('WEBOOB_LOCAL_BACKENDS',
os.getenv('WEBOOB_BACKENDS',
os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')), 'weboob', 'backends')))
modpath = os.getenv('WEBOOB_MODULES', os.path.join(project, 'modules'))
with open(os.path.join(wd, 'sources.list'), 'w') as f:
f.write("file://%s\n" % modpath)
# Hide output unless there is an error
p = subprocess.Popen(
[sys.executable, os.path.join(project, 'scripts', 'weboob-config'), 'update', '-d'],
env=env,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
s = p.communicate()
if p.returncode != 0:
print(s[0])
if p.returncode > 1:
sys.exit(p.returncode)
if os.path.exists(script):
spath = script
else:
spath = os.path.join(project, 'scripts', script)
os.execvpe(
sys.executable,
[sys.executable, '-s'] + pyargs + [spath] + args,
env)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/local_run.sh 0000775 0000000 0000000 00000000204 13507732170 0024062 0 ustar 00root root 0000000 0000000 #!/bin/sh
set -e
. "$(dirname $0)/common.sh"
$PYTHON "$(dirname $0)/stale_pyc.py"
exec $PYTHON "$(dirname $0)/local_run.py" "$@"
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/make_man.py 0000775 0000000 0000000 00000024454 13507732170 0023707 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright(C) 2010-2018 Laurent Bachelier
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with weboob. If not, see .
from __future__ import absolute_import, print_function
import imp
import inspect
import optparse
import os
import re
import sys
import tempfile
import time
from datetime import datetime
from textwrap import dedent
from weboob.tools.application.base import Application
BASE_PATH = os.path.join(os.path.dirname(__file__), os.pardir)
DEST_DIR = 'man'
COMP_PATH = 'tools/weboob_bash_completion'
class ManpageHelpFormatter(optparse.HelpFormatter):
def __init__(self,
app,
indent_increment=0,
max_help_position=0,
width=80,
short_first=1):
optparse.HelpFormatter.__init__(self, indent_increment, max_help_position, width, short_first)
self.app = app
def format_heading(self, heading):
return ".SH %s\n" % heading.upper()
def format_usage(self, usage):
txt = ''
for line in usage.split('\n'):
line = line.lstrip().split(' ', 1)
if len(txt) > 0:
txt += '.br\n'
txt += '.B %s\n' % line[0]
arg_re = re.compile(r'([\[\s])([\w_]+)')
args = re.sub(arg_re, r"\1\\fI\2\\fR", line[1])
txt += args
txt += '\n'
return '.SH SYNOPSIS\n%s' % txt
def format_description(self, description):
desc = u'.SH DESCRIPTION\n.LP\n\n%s\n' % description
if hasattr(self.app, 'CAPS'):
self.app.weboob.modules_loader.load_all()
caps = self.app.CAPS if isinstance(self.app.CAPS, tuple) else (self.app.CAPS,)
modules = []
for name, module in self.app.weboob.modules_loader.loaded.items():
if module.has_caps(*caps):
modules.append(u'* %s (%s)' % (name, module.description))
if len(modules) > 0:
desc += u'\n.SS Supported websites:\n'
desc += u'\n.br\n'.join(sorted(modules))
return desc
def format_commands(self, commands):
s = u''
for section, cmds in commands.items():
if len(cmds) == 0:
continue
s += '.SH %s COMMANDS\n' % section.upper()
for cmd in sorted(cmds):
s += '.TP\n'
h = cmd.split('\n')
if ' ' in h[0]:
cmdname, args = h[0].split(' ', 1)
arg_re = re.compile(r'([A-Z_]+)')
args = re.sub(arg_re, r"\\fI\1\\fR", args)
s += '\\fB%s\\fR %s' % (cmdname, args)
else:
s += '\\fB%s\\fR' % h[0]
s += '%s\n' % '\n.br\n'.join(h[1:])
return s
def format_option_strings(self, option):
opts = optparse.HelpFormatter.format_option_strings(self, option).split(", ")
return ".TP\n" + ", ".join("\\fB%s\\fR" % opt for opt in opts)
def main():
scripts_path = os.path.join(BASE_PATH, "scripts")
files = os.listdir(scripts_path)
completions = dict()
# Create a fake "scripts" modules to import the scripts into
sys.modules["scripts"] = imp.new_module("scripts")
for fname in files:
fpath = os.path.join(scripts_path, fname)
if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
with open(fpath) as f:
# Python will likely want create a compiled file, we provide a place
tmpdir = os.path.join(tempfile.gettempdir(), "weboob", "make_man")
if not os.path.isdir(tmpdir):
os.makedirs(tmpdir)
tmpfile = os.path.join(tmpdir, fname)
desc = ("", "U", imp.PY_SOURCE)
try:
script = imp.load_module("scripts.%s" % fname, f, tmpfile, desc)
except ImportError as e:
print("Unable to load the %s script (%s)"
% (fname, e), file=sys.stderr)
else:
print("Loaded %s" % fname)
# Find the applications we can handle
for klass in script.__dict__.values():
if inspect.isclass(klass) and issubclass(klass, Application) and klass.VERSION:
completions[fname] = analyze_application(klass, fname)
finally:
# Cleanup compiled files if needed
if (os.path.isfile(tmpfile + "c")):
os.unlink(tmpfile + "c")
write_completions(completions)
def format_title(title):
return re.sub(r'^(.+):$', r'.SH \1\n.TP', title.group().upper())
# XXX useful because the PyQt QApplication destructor crashes sometimes. By
# 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
# really a problem.
applications = []
def analyze_application(app, script_name):
application = app()
applications.append(application)
formatter = ManpageHelpFormatter(application)
# patch the application
application._parser.prog = "%s" % script_name
application._parser.formatter = formatter
helptext = application._parser.format_help(formatter)
cmd_re = re.compile(r'^.+ Commands:$', re.MULTILINE)
helptext = re.sub(cmd_re, format_title, helptext)
helptext = helptext.replace("-", r"\-")
coding = r'.\" -*- coding: utf-8 -*-'
comment = r'.\" This file was generated automatically by tools/make_man.sh.'
header = '.TH %s 1 "%s" "%s %s"' % (script_name.upper(), time.strftime("%d %B %Y"),
script_name, app.VERSION.replace('.', '\\&.'))
name = ".SH NAME\n%s \- %s" % (script_name, application.SHORT_DESCRIPTION)
condition = """.SH CONDITION
The \-c and \-\-condition is a flexible way to filter and get only interesting results. It supports conditions on numerical values, dates, durations and strings. Dates are given in YYYY\-MM\-DD or YYYY\-MM\-DD HH:MM format. Durations look like XhYmZs where X, Y and Z are integers. Any of them may be omitted. For instance, YmZs, XhZs or Ym are accepted.
The syntax of one expression is "\\fBfield operator value\\fR". The field to test is always the left member of the expression.
.LP
The field is a member of the objects returned by the command. For example, a bank account has "balance", "coming" or "label" fields.
.SS The following operators are supported:
.TP
=
Test if object.field is equal to the value.
.TP
!=
Test if object.field is not equal to the value.
.TP
>
Test if object.field is greater than the value. If object.field is date, return true if value is before that object.field.
.TP
<
Test if object.field is less than the value. If object.field is date, return true if value is after that object.field.
.TP
|
This operator is available only for string fields. It works like the Unix standard \\fBgrep\\fR command, and returns True if the pattern specified in the value is in object.field.
.SS Expression combination
.LP
You can make a expression combinations with the keywords \\fB" AND "\\fR, \\fB" OR "\\fR an \\fB" LIMIT "\\fR.
.LP
The \\fBLIMIT\\fR keyword can be used to limit the number of items upon which running the expression. \\fBLIMIT\\fR can only be placed at the end of the expression followed by the number of elements you want.
.SS Examples:
.nf
.B boobank ls \-\-condition 'label=Livret A'
.fi
Display only the "Livret A" account.
.PP
.nf
.B boobank ls \-\-condition 'balance>10000'
.fi
Display accounts with a lot of money.
.PP
.nf
.B boobank history account@backend \-\-condition 'label|rewe'
.fi
Get transactions containing "rewe".
.PP
.nf
.B boobank history account@backend \-\-condition 'date>2013\-12\-01 AND date<2013\-12\-09'
.fi
Get transactions betweens the 2th December and 8th December 2013.
.PP
.nf
.B boobank history account@backend \-\-condition 'date>2013\-12\-01 LIMIT 10'
.fi
Get transactions after the 2th December in the last 10 transactions
"""
footer = """.SH COPYRIGHT
%s
.LP
For full copyright information see the COPYING file in the weboob package.
.LP
.RE
.SH FILES
"~/.config/weboob/backends" """ % application.COPYRIGHT.replace('YEAR', '%d' % datetime.today().year)
if len(app.CONFIG) > 0:
footer += '\n\n "~/.config/weboob/%s"' % app.APPNAME
# Skip internal applications.
footer += "\n\n.SH SEE ALSO\nHome page: http://weboob.org/applications/%s" % application.APPNAME
mantext = u"%s\n%s\n%s\n%s\n%s\n%s\n%s" % (coding, comment, header, name, helptext, condition, footer)
with open(os.path.join(BASE_PATH, DEST_DIR, "%s.1" % script_name), 'w+') as manfile:
for line in mantext.split('\n'):
manfile.write('%s\n' % line.lstrip().encode('utf-8'))
print("wrote %s/%s.1" % (DEST_DIR, script_name))
return application._shell_completion_items()
def write_completions(completions):
compscript = dedent('''
# Weboob completion for Bash (automatically generated by tools/make_man.sh)
#
# vim: filetype=sh expandtab softtabstop=4 shiftwidth=4
#
# This file is part of weboob.
#
# This script can be distributed under the same license as the
# weboob or bash packages.
''')
for name, items in completions.items():
compscript += dedent('''
_weboob_{1}()
{{
local cur args
COMPREPLY=()
cur=${{COMP_WORDS[COMP_CWORD]}}
args="{2}"
COMPREPLY=( $(compgen -o default -W "${{args}}" -- "$cur" ) )
}}
complete -F _weboob_{1} {0}
''').format(name, name.replace('-', '_'), ' '.join(items))
with open(os.path.join(BASE_PATH, COMP_PATH), 'w') as f:
f.write(compscript)
if __name__ == '__main__':
sys.exit(main())
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/make_man.sh 0000775 0000000 0000000 00000001510 13507732170 0023655 0 ustar 00root root 0000000 0000000 #!/bin/sh
# stop on failure
set -e
. "$(dirname $0)/common.sh"
# Use C local to avoid local dates in headers
export LANG=en_US.utf8
# disable termcolor
export ANSI_COLORS_DISABLED=1
[ -z "${TMPDIR}" ] && TMPDIR="/tmp"
# do not allow undefined variables anymore
set -u
WEBOOB_TMPDIR=$(mktemp -d "${TMPDIR}/weboob_man.XXXXXX")
# path to sources
WEBOOB_DIR=$(cd $(dirname $0)/.. && pwd -P)
touch "${WEBOOB_TMPDIR}/backends"
chmod 600 "${WEBOOB_TMPDIR}/backends"
echo "file://$WEBOOB_DIR/modules" > "${WEBOOB_TMPDIR}/sources.list"
export WEBOOB_WORKDIR="${WEBOOB_TMPDIR}"
export WEBOOB_DATADIR="${WEBOOB_TMPDIR}"
export PYTHONPATH="${WEBOOB_DIR}"
$PYTHON "${WEBOOB_DIR}/scripts/weboob-config" update
$PYTHON "${WEBOOB_DIR}/tools/make_man.py"
# allow failing commands past this point
STATUS=$?
rm -rf "${WEBOOB_TMPDIR}"
exit $STATUS
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/modules_testing_grid.py 0000775 0000000 0000000 00000004003 13507732170 0026335 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Script to format XUNIT output from unittests as a JSON string ready to be sent
to a [Weboob-CI](https://github.com/Phyks/weboob-ci) instance.
* `XUNIT` is the XUNIT file to handle.
* `ORIGIN` is an origin string as described in the Weboob-CI documentation
(basically just a string to identify the source of the unittests results).
"""
from __future__ import print_function
import json
import sys
import xunitparser
def main(xunit, origin):
with open(xunit, "r") as fh:
ts, tr = xunitparser.parse(fh)
# Get test results for each module
modules = {}
other_testcases = []
for tc in ts:
if tc.classname.startswith("weboob."):
other_testcases.append(repr(tc))
continue
module = tc.classname.split(".")[0]
# In the following, we consider
# bad > skipped > good
# and only make update of a module status according to this order
if tc.good:
if tc.skipped:
# Set to skipped only if previous test was good
if module not in modules or modules[module] == "good":
modules[module] = "skipped"
else:
# Set to good only if no previous result
if module not in modules:
modules[module] = "good"
else:
# Always set to bad on failed test
modules[module] = "bad"
# Agregate results by test result rather than module
results = {
"good": [],
"bad": [],
"skipped": []
}
for module in modules:
results[modules[module]].append(module)
return {
"origin": origin,
"modules": results,
"others": other_testcases
}
if __name__ == "__main__":
if len(sys.argv) < 3:
sys.exit("Usage: %s XUNIT_FILE ORIGIN" % (sys.argv[0]))
print(
json.dumps(
main(sys.argv[1], sys.argv[2]),
sort_keys=True, indent=4, separators=(',', ': ')
)
)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/py3-compatible.modules 0000664 0000000 0000000 00000003036 13507732170 0025775 0 ustar 00root root 0000000 0000000 ##
# this file declares which modules are compatible with python3 and should be checked with pyflakes3
##
750g
adecco
afer
agendaculturel
agendadulibre
allrecipes
amazon
ameli
americanexpress
anticaptcha
amundi
apec
arte
aum
avendrealouer
axabanque
bandcamp
banqueaccord
banquepopulaire
barclays
becm
bforbank
bibliothequesparis
billetreduc
binck
biplan
blablacar
blogspot
bnporc
bnppere
bolden
boursorama
bouygues
bp
bred
btmon
btpbanque
caels
caissedepargne
capeasi
chronopost
cic
cices
citibank
cmb
cmes
cmmc
cmso
colissimo
cragr
creditcooperatif
creditdunord
creditdunordpee
creditmutuel
cuisineaz
deathbycaptcha
delubac
dlfp
ebonics
edf
ekwateur
entreparticuliers
erehsbc
esalia
explorimmo
feedly
foncia
fortuneo
francetelevisions
freemobile
freeteknomusic
funmooc
genericnewspaper
github
gmf
googletranslate
groupamaes
hsbc
hybride
imdb
imgur
indeed
infomaniak
ing
ipinfodb
jcvelaux
jirafeau
lameteoagricole
larousse
lcl
ldlc
leboncoin
lefigaro
liberation
limetorrents
linebourse
linuxjobs
logicimmo
lolix
lucca
lutim
lyricsmode
manpower
marmiton
mediawiki
meteofrance
monster
myfoncia
n26
nalo
nectarine
nef
nova
oney
opensubtitles
orange
ouifm
pap
pariskiwi
paroles2chansons
parolesmania
pastealacon
pastebin
peertube
piratebay
pixtoilelibre
podnapisi
popolemploi
pornhub
ratp
razibus
reddit
redmine
regionsjob
relaiscolis
s2e
seloger
senscritique
societegenerale
somafm
spirica
sprunge
sueurdemetal
supertoinette
suravenir
themisbanque
tumblr
tvsubtitles
twitter
vimeo
vlille
weather
wordreference
xhamster
yggtorrent
yomoni
youjizz
youporn
youtube
zerobin
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/pyflakes.sh 0000775 0000000 0000000 00000005537 13507732170 0023740 0 ustar 00root root 0000000 0000000 #!/bin/sh -u
. "$(dirname $0)/common.sh"
err=0
cd $(dirname $0)/..
PY3MODS=$(grep -v '^#' ./tools/py3-compatible.modules|tr '\n' '|'|sed 's/|$//')
MODULE_FILES=$(git ls-files modules|grep '\.py$')
MODULE_FILES3=$(printf "%s\n" $MODULE_FILES|grep -E -w "^modules/(${PY3MODS})")
PYFILES=$(git ls-files | grep '^scripts\|\.py$'|grep -v boilerplate_data|grep -v stable_backport_data|grep -v '^modules'|grep -v '^contrib')
PYFILES3="$PYFILES $MODULE_FILES3"
PYFILES="$PYFILES $MODULE_FILES"
grep -n 'class [^( ]\+:$' ${PYFILES} && echo 'Error: old class style found, always inherit object' && err=3
grep -n '[[:space:]]$' ${PYFILES} && echo 'Error: tabs or trailing whitespace found, remove them' && err=4
grep -Fn '.setlocale' ${PYFILES} && echo 'Error: do not use setlocale' && err=5
grep -Fn '__future__ import with_statement' ${PYFILES} && echo 'Error: with_statement useless as we do not support Python 2.5' && err=6
grep -nE '^[[:space:]]+except [[:alnum:] ]+,[[:alnum:] ]+' ${PYFILES} && echo 'Error: use new "as" way of naming exceptions' && err=7
grep -nE "^ *print " ${PYFILES} && echo 'Error: Use the print function' && err=8
grep -Fn ".has_key" ${PYFILES} && echo 'Error: Deprecated, use operator "in"' && err=9
grep -Fn "os.isatty" ${PYFILES} && echo 'Error: Use stream.isatty() instead of os.isatty(stream.fileno())' && err=10
grep -Fn "raise StopIteration" ${PYFILES} && echo 'Error: PEP 479' && err=11
grep -nE "\.iter(keys|values|items)\(\)" ${PYFILES3} | grep -Fv "six.iter" && echo 'Error: iterkeys/itervalues/iteritems is forbidden' && err=12
grep -nE "^ *print(\(| )" ${MODULE_FILES} && echo 'Error: Use of print in modules is forbidden, use logger instead' && err=20
grep -n xrange ${MODULE_FILES3} && echo 'Error: xrange is forbidden' && err=21
grep -nE "from (urllib|urlparse) import" ${MODULE_FILES3} && echo 'Error: python2 urllib is forbidden' && err=22
grep -nE "^import (urllib|urlparse)$" ${MODULE_FILES3} && echo 'Error: python2 urllib is forbidden' && err=22
grep -nE "HEADLESS[[:space:]]*=[[:space:]]*False" ${MODULE_FILES} && echo 'Error: HEADLESS must be set back to True' && err=23
if [ ${VER} -eq 2 ]
then
if ${PYTHON2} -c "import flake8" 2>/dev/null; then
FLAKER2=flake8
OPT2="--select=E9,F"
elif ${PYTHON2} -c "import pyflakes" 2>/dev/null; then
FLAKER2=pyflakes
OPT2=
else
echo "flake8 or pyflakes for python2 not found"
err=1
fi
if [ ${err} -ne 1 ]; then
$PYTHON2 -m ${FLAKER2} ${OPT2} ${PYFILES} || err=32
fi
fi
if [ ${VER} -eq 3 ]
then
if ${PYTHON3} -c "import flake8" 2>/dev/null; then
FLAKER3=flake8
OPT3="--select=E9,F"
elif ${PYTHON3} -c "import pyflakes" 2>/dev/null; then
FLAKER3=pyflakes
OPT3=
else
echo "flake8 or pyflakes for python3 not found"
err=1
fi
if [ ${err} -ne 1 ]; then
$PYTHON3 -m ${FLAKER3} ${OPT3} ${PYFILES3} || exit 33
fi
fi
exit $err
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/pyreverse.sh 0000775 0000000 0000000 00000000420 13507732170 0024130 0 ustar 00root root 0000000 0000000 #!/bin/sh
#
# Examples:
# pyreverse.sh weboob.backends.aum
#
# pyreverse is included in pylint Debian package
usage() {
echo "pyreverse.sh "
exit
}
[ -z "$1" ] && usage
PYTHONPATH="$(dirname $0)/../modules/$1" pyreverse -p "$1" -o pdf -a1 -s1 "."
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/release.py 0000775 0000000 0000000 00000015470 13507732170 0023555 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
import argparse
import configparser
import os
import re
import sys
import datetime
from subprocess import check_call, check_output
from weboob.tools.misc import to_unicode
WORKTREE = 'release_tmp'
OPTIONS = ['--qt', '--xdg']
def make_tarball(tag, wheel):
# Create and enter a temporary worktree
if os.path.isdir(WORKTREE):
check_call(['git', 'worktree', 'remove', '--force', WORKTREE])
check_call(['git', 'worktree', 'add', WORKTREE, tag])
assert os.path.isdir(WORKTREE)
os.chdir(WORKTREE)
check_call([sys.executable, 'setup.py'] + OPTIONS +
['sdist',
'--keep',
'--dist-dir', '../dist'])
if wheel:
check_call([sys.executable, 'setup.py'] + OPTIONS +
['bdist_wheel',
'--keep',
'--dist-dir', '../dist'])
# Clean up the temporary worktree
os.chdir(os.pardir)
check_call(['git', 'worktree', 'remove', '--force', WORKTREE])
assert not os.path.isdir(WORKTREE)
files = ['dist/weboob-%s.tar.gz' % tag]
if wheel:
files.append('dist/weboob-%s-py2.py3-none-any.whl' % tag)
for f in files:
if not os.path.exists(f):
raise Exception('Generated file not found at %s' % f)
else:
print('Generated file: %s' % f)
print('To upload to PyPI, run: twine upload -s %s' % ' '.join(files))
def changed_modules(changes, changetype):
for change in changes:
change = change.decode('utf-8').split()
if change[0] == changetype:
m = re.match(r'modules/([^/]+)/__init__\.py', change[1])
if m:
yield m.group(1)
def get_caps(module, config):
try:
return sorted(c for c in config[module]['capabilities'].split() if c != 'CapCollection')
except KeyError:
return ['**** FILL ME **** (running weboob update could help)']
def new_modules(start, end):
os.chdir(os.path.join(os.path.dirname(__file__), os.path.pardir))
modules_info = configparser.ConfigParser()
with open('modules/modules.list') as f:
modules_info.read_file(f)
git_cmd = ['git', 'diff', '--no-renames', '--name-status', '%s..%s' % (start, end), '--', 'modules/']
added_modules = sorted(changed_modules(check_output(git_cmd).splitlines(), 'A'))
deleted_modules = sorted(changed_modules(check_output(git_cmd).splitlines(), 'D'))
for added_module in added_modules:
yield 'New %s module (%s)' % (added_module, ', '.join(get_caps(added_module, modules_info)))
for deleted_module in deleted_modules:
yield 'Deleted %s module' % deleted_module
def changelog(start, end='HEAD'):
def sortkey(d):
"""Put the commits with multiple domains at the end"""
return (len(d), d)
commits = {}
for commithash in check_output(['git', 'rev-list', '{}..{}'.format(start, end)]).splitlines():
title, domains = commitinfo(commithash)
commits.setdefault(domains, []).append(title)
for line in new_modules(start, end):
commits.setdefault(('General',), []).append(line)
cl = ''
for domains in sorted(commits.keys(), key=sortkey):
cl += '\n\n\t' + '\n\t'.join(domains)
for title in commits[domains]:
cl += '\n\t* ' + title
return cl.lstrip('\n')
def domain(path):
dirs = os.path.dirname(path).split('/')
if dirs == ['']:
return 'General: Core'
if dirs[0] == 'man' or path == 'tools/py3-compatible.modules':
return None
if dirs[0] == 'weboob':
try:
if dirs[1] in ('core', 'tools'):
return 'General: Core'
elif dirs[1] == 'capabilities':
return 'Capabilities'
elif dirs[1] == 'browser':
try:
if dirs[2] == 'filters':
return 'Browser: Filters'
except IndexError:
return 'Browser'
elif dirs[1] == 'applications':
try:
return 'Applications: {}'.format(dirs[2])
except IndexError:
return 'Applications'
elif dirs[1] == 'application':
try:
return 'Applications: {}'.format(dirs[2].title())
except IndexError:
return 'Applications'
except IndexError:
return 'General: Core'
if dirs[0] in ('contrib', 'tools'):
return 'Tools'
if dirs[0] in ('docs', 'icons'):
return 'Documentation'
if dirs[0] == 'modules':
try:
return 'Modules: {}'.format(dirs[1])
except IndexError:
return 'General: Core'
return 'Unknown'
def commitinfo(commithash):
info = check_output(['git', 'show', '--format=%s', '--name-only', commithash]).decode('utf-8').splitlines()
title = to_unicode(info[0])
domains = set([domain(p) for p in info[2:] if domain(p)])
if 'Unknown' in domains and len(domains) > 1:
domains.remove('Unknown')
if not domains or len(domains) > 5:
domains = set(['Unknown'])
if 'Unknown' not in domains:
# When the domains are known, hide the title prefixes
title = re.sub(r'^(?:[\w\./\s]+:|\[[\w\./\s]+\])\s*', '', title, flags=re.UNICODE)
return title, tuple(sorted(domains))
def previous_version():
"""
Get the highest version tag
"""
for v in check_output(['git', 'tag', '-l', '*.*', '--sort=-v:refname']).splitlines():
return v.decode()
def prepare(start, end, version):
print('Weboob %s (%s)\n' % (version, datetime.date.today().strftime('%Y-%m-%d')))
print(changelog(start, end))
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Prepare and export a release.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
epilog='This is mostly meant to be called from release.sh for now.',
)
subparsers = parser.add_subparsers()
prepare_parser = subparsers.add_parser(
'prepare',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
prepare_parser.add_argument('version')
prepare_parser.add_argument('--start', default=previous_version(), help='Commit of the previous release')
prepare_parser.add_argument('--end', default='HEAD', help='Last commit before the new release')
prepare_parser.set_defaults(mode='prepare')
tarball_parser = subparsers.add_parser(
'tarball',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
tarball_parser.add_argument('tag')
tarball_parser.add_argument('--no-wheel', action='store_false', dest='wheel')
tarball_parser.set_defaults(mode='tarball')
args = parser.parse_args()
if args.mode == 'prepare':
prepare(args.start, args.end, args.version)
elif args.mode == 'tarball':
make_tarball(args.tag, args.wheel)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/release.sh 0000775 0000000 0000000 00000002510 13507732170 0023526 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# This script is used to release a version.
set -e
cd "$(dirname $0)/.."
function set_version {
echo -n "Replacing version in source files to $1... "
sed -i "s/^\(\s*\)\(VERSION\|version\|release\|__version__\)\( *\)=\( *\)[\"'][0-9]\+\..\+[\"']\(,\?\)$/\1\2\3=\4'$1'\5/g" $(git ls-files -x contrib | grep -v "\.svg$")
echo -e "done.\n"
}
if [ -z "$1" ]; then
echo "Syntax: $0 VERSION"
exit 1
fi
VERSION=$1
echo "Generating ChangeLog..."
export LANG=en_US.utf8
mv ChangeLog ChangeLog.old
tools/release.py prepare $VERSION > ChangeLog
echo -e "\n" >> ChangeLog
cat ChangeLog.old >> ChangeLog
rm -f ChangeLog.old
vi +2 ChangeLog
set_version $VERSION
echo "Building Qt applications..."
./setup.py --qt sdist bdist clean -a || exit 1
echo "Generating manpages..."
tools/make_man.sh
echo -e "done!\n"
# in case there are new manpages not included in the git tree.
git add man/*
echo "Release commit:"
git commit -a -m "Weboob $VERSION released"
echo -ne "\n"
echo "Release tag:"
git tag $VERSION -s -m "Weboob $VERSION"
echo -ne "\n"
tools/release.py tarball $VERSION
echo -ne "\nDo you want to change the version number (y/n) "
read change_version
if [ "$change_version" = "y" ]; then
echo -n "Enter the new version number: "
read NEW_VERSION
set_version $NEW_VERSION
git commit -a -m "bump to $NEW_VERSION"
fi
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/run_tests.sh 0000775 0000000 0000000 00000013160 13507732170 0024137 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# Mai available environment variables
# * RSYNC_TARGET: target on which to rsync the xunit output.
# * XUNIT_OUT: file in which xunit output should be saved.
# * WEBOOB_BACKENDS: path to the Weboob backends file to use.
# * WEBOOB_CI_TARGET: URL of your Weboob-CI instance.
# * WEBOOB_CI_ORIGIN: origin for the Weboob-CI data.
# stop on failure
set -e
. "$(dirname $0)/common.sh"
if [ -z "${PYTHON}" ]; then
echo "Python required"
exit 1
fi
if ! $PYTHON -c "import nose" 2>/dev/null; then
echo "python-nose required"
exit 1
fi
TEST_CORE=1
TEST_MODULES=1
for i in "$@"
do
case $i in
--no-modules)
TEST_MODULES=0
shift
;;
--no-core)
TEST_CORE=0
shift
;;
*)
;;
esac
done
# path to sources
WEBOOB_DIR=$(cd $(dirname $0)/.. && pwd -P)
BACKEND="${1}"
if [ -z "${WEBOOB_WORKDIR}" ]; then
# use the old workdir by default
WEBOOB_WORKDIR="${HOME}/.weboob"
# but if we can find a valid xdg workdir, switch to it
[ "${XDG_CONFIG_HOME}" != "" ] || XDG_CONFIG_HOME="${HOME}/.config"
[ -d "${XDG_CONFIG_HOME}/weboob" ] && WEBOOB_WORKDIR="${XDG_CONFIG_HOME}/weboob"
fi
[ -z "${TMPDIR}" ] && TMPDIR="/tmp"
WEBOOB_TMPDIR=$(mktemp -d "${TMPDIR}/weboob_test.XXXXXX")
[ -z "${WEBOOB_BACKENDS}" ] && WEBOOB_BACKENDS="${WEBOOB_WORKDIR}/backends"
[ -z "${WEBOOB_MODULES}" ] && WEBOOB_MODULES="${WEBOOB_DIR}/modules"
[ -z "${PYTHONPATH}" ] && PYTHONPATH=""
# allow private environment setup
[ -f "${WEBOOB_WORKDIR}/pre-test.sh" ] && source "${WEBOOB_WORKDIR}/pre-test.sh"
# setup xunit reporting (buildbot slaves only)
if [ -n "${RSYNC_TARGET}" ]; then
# by default, builder name is containing directory name
[ -z "${BUILDER_NAME}" ] && BUILDER_NAME=$(basename $(readlink -e $(dirname $0)/../..))
XUNIT_OUT="${WEBOOB_TMPDIR}/xunit.xml"
else
RSYNC_TARGET=""
fi
# Avoid undefined variables
if [ ! -n "${XUNIT_OUT}" ]; then
XUNIT_OUT=""
fi
# Handle Weboob-CI variables
if [ -n "${WEBOOB_CI_TARGET}" ]; then
if [ ! -n "${WEBOOB_CI_ORIGIN}" ]; then
WEBOOB_CI_ORIGIN="Weboob unittests run"
fi
# Set up xunit reporting
XUNIT_OUT="${WEBOOB_TMPDIR}/xunit.xml"
else
WEBOOB_CI_TARGET=""
fi
# do not allow undefined variables anymore
set -u
if [ -f "${WEBOOB_BACKENDS}" ]; then
cp "${WEBOOB_BACKENDS}" "${WEBOOB_TMPDIR}/backends"
else
touch "${WEBOOB_TMPDIR}/backends"
chmod go-r "${WEBOOB_TMPDIR}/backends"
fi
# xunit nose setup
if [ -n "${XUNIT_OUT}" ]; then
XUNIT_ARGS="--with-xunit --xunit-file=${XUNIT_OUT}"
else
XUNIT_ARGS=""
fi
${PYTHON} "$(dirname $0)/stale_pyc.py"
echo "file://${WEBOOB_MODULES}" > "${WEBOOB_TMPDIR}/sources.list"
export WEBOOB_WORKDIR="${WEBOOB_TMPDIR}"
export WEBOOB_DATADIR="${WEBOOB_TMPDIR}"
export PYTHONPATH="${WEBOOB_DIR}:${PYTHONPATH}"
export NOSE_NOPATH="1"
if [[ ($TEST_MODULES = 1) || (-n "${BACKEND}") ]]; then
${PYTHON} "${WEBOOB_DIR}/scripts/weboob-config" update
fi
# allow failing commands past this point
set +e
set -o pipefail
STATUS_CORE=0
STATUS=0
if [ -n "${BACKEND}" ]; then
${PYTHON} -m nose -c /dev/null --logging-level=DEBUG -sv "${WEBOOB_MODULES}/${BACKEND}/test.py" ${XUNIT_ARGS}
STATUS=$?
else
if [ $TEST_CORE = 1 ]; then
echo "=== Weboob ==="
CORE_TESTS=$(mktemp)
${PYTHON} -m nose --cover-package weboob -c ${WEBOOB_DIR}/setup.cfg --logging-level=DEBUG -sv 2>&1 | tee "${CORE_TESTS}"
STATUS_CORE=$?
CORE_STMTS=$(grep "TOTAL" ${CORE_TESTS} | awk '{ print $2; }')
CORE_MISS=$(grep "TOTAL" ${CORE_TESTS} | awk '{ print $3; }')
CORE_COVERAGE=$(grep "TOTAL" ${CORE_TESTS} | awk '{ print $4; }')
rm ${CORE_TESTS}
fi
if [ $TEST_MODULES = 1 ]; then
echo "=== Modules ==="
MODULES_TESTS=$(mktemp)
MODULES_TO_TEST=$(find "${WEBOOB_MODULES}" -name "test.py" | sort | xargs echo)
${PYTHON} -m nose --with-coverage --cover-package modules -c /dev/null --logging-level=DEBUG -sv ${XUNIT_ARGS} ${MODULES_TO_TEST} 2>&1 | tee ${MODULES_TESTS}
STATUS=$?
MODULES_STMTS=$(grep "TOTAL" ${MODULES_TESTS} | awk '{ print $2; }')
MODULES_MISS=$(grep "TOTAL" ${MODULES_TESTS} | awk '{ print $3; }')
MODULES_COVERAGE=$(grep "TOTAL" ${MODULES_TESTS} | awk '{ print $4; }')
rm ${MODULES_TESTS}
fi
# Compute total coverage
echo "=== Total coverage ==="
if [ $TEST_CORE = 1 ]; then
echo "CORE COVERAGE: ${CORE_COVERAGE}"
fi
if [ $TEST_MODULES = 1 ]; then
echo "MODULES COVERAGE: ${MODULES_COVERAGE}"
fi
if [[ ($TEST_CORE = 1) && ($TEST_MODULES = 1) ]]; then
TOTAL_STMTS=$((${CORE_STMTS} + ${MODULES_STMTS}))
TOTAL_MISS=$((${CORE_MISS} + ${MODULES_MISS}))
TOTAL_COVERAGE=$((100 * (${TOTAL_STMTS} - ${TOTAL_MISS}) / ${TOTAL_STMTS}))
echo "TOTAL: ${TOTAL_COVERAGE}%"
fi
fi
# Rsync xunit transfer
if [ -n "${RSYNC_TARGET}" ]; then
rsync -iz "${XUNIT_OUT}" "${RSYNC_TARGET}/${BUILDER_NAME}-$(date +%s).xml"
rm "${XUNIT_OUT}"
fi
# Weboob-CI upload
if [ -n "${WEBOOB_CI_TARGET}" ]; then
JSON_MODULE_MATRIX=$(${PYTHON} "${WEBOOB_DIR}/tools/modules_testing_grid.py" "${XUNIT_OUT}" "${WEBOOB_CI_ORIGIN}")
curl -H "Content-Type: application/json" --data "${JSON_MODULE_MATRIX}" "${WEBOOB_CI_TARGET}/api/v1/modules"
rm "${XUNIT_OUT}"
fi
# safe removal
if [[ ($TEST_MODULES = 1) || (-n "${BACKEND}") ]]; then
rm -r "${WEBOOB_TMPDIR}/icons" "${WEBOOB_TMPDIR}/repositories" "${WEBOOB_TMPDIR}/modules" "${WEBOOB_TMPDIR}/keyrings"
fi
rm "${WEBOOB_TMPDIR}/backends" "${WEBOOB_TMPDIR}/sources.list"
rmdir "${WEBOOB_TMPDIR}"
[ $STATUS_CORE -gt 0 ] && exit $STATUS_CORE
exit $STATUS
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/setup-virtualenv.sh 0000775 0000000 0000000 00000002725 13507732170 0025453 0 ustar 00root root 0000000 0000000 #!/bin/sh -e
# install weboob inside a virtualenv, optionally with an associated weboob workdir
# can be combined with git-worktree
cd "$(dirname $0)/.."
SRC=$PWD
source=
VDIR=
usage () {
cat << EOF
Usage: $0 [-s] [-d DIR]
-s point sources.list to $SRC/modules instead of updates.weboob.org
-d DIR install virtualenv in DIR instead of a new dir
EOF
}
while getopts hsd: name
do
case $name in
s) source=y;;
d) VDIR="$OPTARG";;
h) usage
exit 0;;
?) usage
exit 2;;
esac
done
shift $(($OPTIND - 1))
PYTHON=${PYTHON-python}
echo "Using weboob source $SRC"
if [ -z "$VDIR" ]
then
VDIR=$(mktemp -d /tmp/weboob.venv.XXXXXX)
fi
cd "$VDIR"
echo "Creating env in $VDIR"
virtualenv -p "$(which "$PYTHON")" --system-site-packages "$VDIR"
. ./bin/activate
echo "Installing weboob in $VDIR"
"$PYTHON" -m pip install "$SRC"
mkdir workdir
export WEBOOB_WORKDIR=$VDIR/workdir
if [ "$source" = y ]
then
echo "file://$SRC/modules" > "$WEBOOB_WORKDIR/sources.list"
fi
./bin/weboob-config update
cat > use-weboob-local.sh << EOF
VDIR="$VDIR"
. "$VDIR/bin/activate"
export WEBOOB_WORKDIR="$VDIR/workdir"
EOF
cat << EOF
Installation complete in $VDIR.
Run ". $VDIR/use-weboob-local.sh" to start using it.
Run "$PYTHON -m pip install -U $SRC" to reinstall the core.
EOF
if [ "$source" != y ]
then
echo "You can add file://$SRC/modules into $VDIR/workdir/sources.list to use local modules instead of downloading modules."
fi
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/stable_backport.py 0000775 0000000 0000000 00000020010 13507732170 0025256 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
from __future__ import print_function
import time
import sys
import re
from contextlib import contextmanager
from os import system, path, makedirs, getenv
from subprocess import check_output, STDOUT, CalledProcessError
from collections import defaultdict
import shutil
from termcolor import colored
STABLE_VERSION = getenv('WEBOOB_BACKPORT_STABLE', '1.3')
DEVEL_BRANCH = getenv('WEBOOB_BACKPORT_DEVEL', 'master')
@contextmanager
def log(message, success='done'):
print('%s... ' % message, end='', flush=True)
start = time.time()
try:
yield
except KeyboardInterrupt:
print(colored('abort', 'red'))
sys.exit(1)
except Exception as e:
print(colored('fail: %s' % e, 'red'))
raise
else:
print('%s %s' % (colored(success, 'green'),
colored('(%.2fs)' % (time.time() - start), 'blue')))
def create_compat_dir(name):
if not path.exists(name):
makedirs(name)
with open(path.join(name, '__init__.py'), 'w'):
pass
MANUAL_PORTS = [
'weboob.tools.captcha.virtkeyboard',
]
MANUAL_PORT_DIR = path.join(path.dirname(__file__), 'stable_backport_data')
class Error(object):
def __init__(self, filename, linenum, message):
self.filename = filename
self.linenum = linenum
self.message = message
self.compat_dir = path.join(path.dirname(filename), 'compat')
def __repr__(self):
return '<%s filename=%r linenum=%s message=%r>' % (type(self).__name__, self.filename, self.linenum, self.message)
def reimport_module(self, module):
# not a weboob module, probably a false positive.
if not module.startswith('weboob'):
return
dirname = module.replace('.', '/')
filename = dirname + '.py'
new_module = module.replace('.', '_')
target = path.join(self.compat_dir, '%s.py' % new_module)
base_module = '.'.join(module.split('.')[:-1])
try:
r = check_output('git show %s:%s' % (DEVEL_BRANCH, filename), shell=True, stderr=STDOUT).decode('utf-8')
except CalledProcessError:
# this file does not exist, perhaps a directory.
return
if module in MANUAL_PORTS:
shutil.copyfile(path.join(MANUAL_PORT_DIR, path.basename(target)), target)
else:
# Copy module from devel to a compat/ sub-module
with open(target, 'w') as fp:
for line in r.split('\n'):
# Replace relative imports to absolute ones
m = re.match(r'^from (\.\.?)([\w_\.]+) import (.*)', line)
if m:
if m.group(1) == '..':
base_module = '.'.join(base_module.split('.')[:-1])
fp.write('from %s.%s import %s\n' % (base_module, m.group(2), m.group(3)))
continue
# Inherit all classes by previous ones, if they already existed.
m = re.match(r'^class (\w+)\(([\w,\s]+)\):(.*)', line)
if m and path.exists(filename) and system('grep "^class %s" %s >/dev/null' % (m.group(1), filename)) == 0:
symbol = m.group(1)
trailing = m.group(3)
fp.write('from %s import %s as _%s\n' % (module, symbol, symbol))
fp.write('class %s(_%s):%s\n' % (symbol, symbol, trailing))
continue
fp.write('%s\n' % line)
# Particular case, in devel some imports have been added to
# weboob/browser/__init__.py
system(r'sed -i -e "s/from weboob.browser import/from weboob.browser.browsers import/g" %s'
% self.filename)
# Replace import to this module by a relative import to the copy in
# compat/
system(r'sed -i -e "%ss/from \([A-Za-z0-9_\.]\+\) import \(.*\)/from .compat.%s import \2/g" %s'
% (self.linenum, new_module, self.filename))
def remove_block(name, start):
lines = []
with open(name, 'r') as fd:
it = iter(fd)
for n in range(start - 1):
lines.append(next(it))
line = next(it)
level = len(re.match(r'^( *)', line).group(1))
for line in it:
if not line.strip():
continue
new = len(re.match(r'^( *)', line).group(1))
if new <= level:
lines.append(line)
break
lines.extend(it)
with open(name, 'w') as fd:
fd.write(''.join(lines))
class NoNameInModuleError(Error):
def fixup(self):
m = re.match(r"No name '(\w+)' in module '([\w\.]+)'", self.message)
module = m.group(2)
self.reimport_module(module)
class ImportErrorError(Error):
def fixup(self):
m = re.match(r"Unable to import '([\w\.]+)'", self.message)
module = m.group(1)
self.reimport_module(module)
class ManualBackport(Error):
def fixup(self):
self.reimport_module(self.message)
def replace_all(expr, dest):
system(r"""for file in $(git ls-files modules | grep '\.py$');
do
sed -i -e "s/""" + expr + '/' + dest + """/g" $file
done""")
def output_lines(cmd):
return check_output(cmd, shell=True, stderr=STDOUT).decode('utf-8').rstrip().split('\n')
class StableBackport(object):
errors = {'E0611': NoNameInModuleError,
'E0401': ImportErrorError,
}
def main(self):
with log('Removing previous compat files'):
system('git rm -q "modules/*/compat/*.py"')
with log('Copying last version of modules from devel'):
system('git checkout --theirs %s modules' % DEVEL_BRANCH)
with log('Replacing version number'):
replace_all(r"""^\(\s*\)\(VERSION\)\( *\)=\( *\)[\"'][0-9]\+\..\+[\"']\(,\?\)$""",
r"""\1\2\3=\4'""" + STABLE_VERSION + r"""'\5""")
with log('Removing staling data'):
system('tools/stale_pyc.py')
system('find modules -type d -empty -delete')
system('git add -u')
with log('Lookup modules errors'):
r = check_output("pylint modules/* -f parseable -E -d all -e no-name-in-module,import-error; exit 0", shell=True, stderr=STDOUT).decode('utf-8')
dirnames = defaultdict(list)
for line in r.split('\n'):
m = re.match(r'([\w\./]+):(\d+): \[(\w+)[^\]]+\] (.*)', line)
if not m:
continue
filename = m.group(1)
linenum = m.group(2)
error = m.group(3)
msg = m.group(4)
dirnames[path.dirname(filename)].append(self.errors[error](filename, linenum, msg))
with log('Searching manual backports'):
for manual in MANUAL_PORTS:
r = check_output("grep -nEr '^from %s import ' modules" % manual, shell=True).strip().decode('utf-8')
for line in r.split('\n'):
m = re.match(r'([\w\./]+):(\d+):.*', line)
filename = m.group(1)
linenum = m.group(2)
target = dirnames[path.dirname(filename)]
for err in target:
if err.filename == filename and err.linenum == linenum:
# an error was already spot on this line
break
else:
target.append(ManualBackport(filename, linenum, manual))
for dirname, errors in sorted(dirnames.items()):
with log('Fixing up %s errors in %s' % (colored(str(len(errors)), 'magenta'),
colored(dirname, 'yellow'))):
compat_dirname = path.join(dirname, 'compat')
create_compat_dir(compat_dirname)
for error in errors:
error.fixup()
system('git add %s' % compat_dirname)
system('git add -u')
if __name__ == '__main__':
StableBackport().main()
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/stable_backport_data/ 0000775 0000000 0000000 00000000000 13507732170 0025701 5 ustar 00root root 0000000 0000000 weboob_tools_captcha_virtkeyboard.py 0000664 0000000 0000000 00000016721 13507732170 0035150 0 ustar 00root root 0000000 0000000 woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/stable_backport_data
import weboob.tools.captcha.virtkeyboard as OLD
# can't import *, __all__ is incomplete...
for attr in dir(OLD):
globals()[attr] = getattr(OLD, attr)
try:
__all__ = OLD.__all__
except AttributeError:
pass
class SimpleVirtualKeyboard(object):
"""Handle a virtual keyboard where "keys" are distributed on a simple grid.
Parameters:
:param cols: Column count of the grid
:type cols: int
:param rows: Row count of the grid
:type rows: int
:param image: File-like object to be used as data source
:type image: file
:param convert: Mode to which convert color of pixels, see
:meth:`Image.Image.convert` for more information
:param matching_symbols: symbol that match all case of image grid from left to right and top
to down, European reading way.
:type matching_symbols: iterable
:param matching_symbols_coords: dict mapping matching website symbols to their image coords
(x0, y0, x1, y1) on grid image from left to right and top to
down, European reading way. It's not symbols in the image.
:type matching_symbols_coords: dict[str:4-tuple(int)]
:param browser: Browser of weboob session.
Allow to dump tiles files in same directory than session folder
:type browser: obj(Browser)
Attributes:
:attribute codesep: Output separator between matching symbols
:type codesep: str
:param margin: Useless image pixel to cut.
See :func:`cut_margin`.
:type margin: 4-tuple(int), same as HTML margin: (top, right, bottom, left).
or 2-tuple(int), (top = bottom, right = left),
or int, top = right = bottom = left
:attribute tile_margin: Useless tile pixel to cut.
See :func:`cut_margin`.
:attribute symbols: Association table between image symbols and md5s
:type symbols: dict[str:str] or dict[str:n-tuple(str)]
:attribute convert: Mode to which convert color of pixels, see
:meth:`Image.Image.convert` for more information
:attribute alter: Allow custom main image alteration. Then overwrite :func:`alter_image`.
:type alter: boolean
"""
codesep = ''
margin = None
tile_margin = None
symbols = None
convert = None
def __init__(self, file, cols, rows, matching_symbols=None, matching_symbols_coords=None, browser=None):
self.cols = cols
self.rows = rows
# Needed even if init is overwrite
self.path = self.build_path(browser)
# Get self.image
self.load_image(file, self.margin, self.convert)
# Get self.tiles
self.get_tiles( matching_symbols=matching_symbols,
matching_symbols_coords=matching_symbols_coords)
# Tiles processing
self.cut_tiles(self.tile_margin)
self.hash_md5_tiles()
def build_path(self, browser=None):
if browser and browser.responses_dirname:
return browser.responses_dirname
else:
return tempfile.mkdtemp(prefix='weboob_session_')
def load_image(self, file, margin=None, convert=None):
self.image = Image.open(file)
# Resize image if margin is given
if margin:
self.image = self.cut_margin(self.image, margin)
if convert:
self.image = self.image.convert(convert)
# Give possibility to alter image before get tiles, overwrite :func:`alter_image`.
self.alter_image()
self.width, self.height = self.image.size
def alter_image(self):
pass
def cut_margin(self, image, margin):
width, height = image.size
# Verify the magin value format
if type(margin) is int:
margin = (margin, margin, margin, margin)
elif len(margin) == 2:
margin = (margin[0], margin[1], margin[0], margin[1])
elif len(margin) == 4:
margin = margin
else:
assert (len(margin) == 3) & (len(margin) > 4), \
"Margin format is wrong."
assert ((margin[0] + margin[2]) < height) & ((margin[1] + margin[3]) < width), \
"Margin is too high, there is not enough pixel to cut."
image = image.crop((0 + margin[3],
0 + margin[0],
width - margin[1],
height - margin[2]
))
return image
def get_tiles(self, matching_symbols=None, matching_symbols_coords=None):
self.tiles = []
# Tiles coords are given
if matching_symbols_coords:
for matching_symbol in matching_symbols_coords:
self.tiles.append(Tile( matching_symbol=matching_symbol,
coords=matching_symbols_coords[matching_symbol]
))
return
assert (not self.width%self.cols) & (not self.height%self.rows), \
"Image width and height are not multiple of cols and rows. Please resize image with attribute `margin`."
# Tiles coords aren't given, calculate them
self.tileW = self.width // self.cols
self.tileH = self.height // self.rows
# Matching symbols aren't given, default value is range(columns*rows)
if not matching_symbols:
matching_symbols = ['%s' % i for i in range(self.cols*self.rows)]
assert len(matching_symbols) == (self.cols*self.rows), \
"Number of website matching symbols is not equal to the number of cases on the image."
# Calculate tiles coords for each matching symbol from 1-dimension to 2-dimensions
for index, matching_symbol in enumerate(matching_symbols):
coords = self.get_tile_coords_in_grid(index)
self.tiles.append(Tile(matching_symbol=matching_symbol, coords=coords))
def get_tile_coords_in_grid(self, case_index):
# Get the top left pixel coords of the tile
x0 = (case_index % self.cols) * self.tileW
y0 = (case_index // self.cols) * self.tileH
# Get the bottom right coords of the tile
x1 = x0 + self.tileW
y1 = y0 + self.tileH
coords = (x0, y0, x1, y1)
return(coords)
def cut_tiles(self, tile_margin=None):
for tile in self.tiles:
tile.image = self.image.crop(tile.coords)
# Resize tile if margin is given
if tile_margin:
for tile in self.tiles:
tile.image = self.cut_margin(tile.image, tile_margin)
def hash_md5_tiles(self):
for tile in self.tiles:
tile.md5 = hashlib.md5(tile.image.tobytes()).hexdigest()
def dump_tiles(self, path):
for tile in self.tiles:
tile.image.save('{}/{}.png'.format(path, tile.md5))
def get_string_code(self, password):
word = []
for digit in password:
for tile in self.tiles:
if tile.md5 in self.symbols[digit]:
word.append(tile.matching_symbol)
break
else:
# Dump file only if the symbol is not found
self.dump_tiles(self.path)
raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s"
% (digit, self.path))
return self.codesep.join(word)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/stale_pyc.py 0000775 0000000 0000000 00000001324 13507732170 0024111 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
from __future__ import print_function
import os
import sys
root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))
verbose = '-v' in sys.argv
excludes = ('.git', '.svn', '__pycache__')
for dirpath, dirnames, filenames in os.walk(root):
for exclude in excludes:
try:
dirnames.remove(exclude)
except ValueError:
pass
for filename in filenames:
if filename.endswith('.pyc') or filename.endswith('pyo'):
if not os.path.exists(os.path.join(dirpath, filename[:-1])):
os.unlink(os.path.join(dirpath, filename))
if verbose:
print(os.path.join(dirpath, filename))
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/weboob_bash_completion 0000664 0000000 0000000 00000056147 13507732170 0026214 0 ustar 00root root 0000000 0000000
# Weboob completion for Bash (automatically generated by tools/make_man.sh)
#
# vim: filetype=sh expandtab softtabstop=4 shiftwidth=4
#
# This file is part of weboob.
#
# This script can be distributed under the same license as the
# weboob or bash packages.
_weboob_weboob_config()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="register help --insecure list -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h add -v --debug --no-keys -s -q --auto-update --nss enable --logging-file --exclude-backends update --version disable --outfile --export-session info --quiet --condition edit confirm modules remove --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboob_config weboob-config
_weboob_weboob_repos()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update create --nss --logging-file --exclude-backends --version --outfile --export-session build --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboob_repos weboob-repos
_weboob_weboob_debug()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="--insecure -B -I --verbose --backends -e -d -a -b -h -v --debug -q --bpython --nss --logging-file --exclude-backends --version --export-session --quiet --save-responses --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboob_debug weboob-debug
_weboob_boobathon()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="addtask tasks help --insecure -O -I --verbose cd cancel --formatter done close --count progress --backends -e -d -f -a -c -b backends --select -n --no-header -h start -v --debug --no-keys -s -q --auto-update --nss remtask --logging-file --exclude-backends --version --outfile members --export-session info --quiet --condition join edit leave --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobathon boobathon
_weboob_galleroob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd download --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_galleroob galleroob
_weboob_webcontentedit()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a log -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file get --exclude-backends --version --outfile --export-session --quiet --condition edit --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_webcontentedit webcontentedit
_weboob_suboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd download --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_suboob suboob
_weboob_wetboobs()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h forecasts -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends --version --outfile --export-session cities --quiet --condition current --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_wetboobs wetboobs
_weboob_boobank()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O advisor -I --verbose cd --formatter --count --backends investment -e -d -f -a recipients -c -b transfer --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss profile --logging-file --exclude-backends --version pocket budgea add_recipient --outfile --export-session --quiet --condition backends list coming --save-responses ls --help history"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobank boobank
_weboob_qbooblyrics()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qbooblyrics qbooblyrics
_weboob_qwebcontentedit()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qwebcontentedit qwebcontentedit
_weboob_qhavedate()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qhavedate qhavedate
_weboob_traveloob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --departure-time --logging-file --exclude-backends --version --outfile --export-session roadmap --quiet --condition stations --arrival-time --save-responses ls --help departures"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_traveloob traveloob
_weboob_qboobmsg()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qboobmsg qboobmsg
_weboob_monboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter -S --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s --smtpd -q --auto-update --nss run --logging-file --exclude-backends --version --outfile --export-session post --quiet --condition --save-responses ls --help once"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_monboob monboob
_weboob_boobtracker()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="comment help --insecure --no-header -O -I --verbose cd --count --formatter --category --author --start -e -d --tracker -a -c -b --assignee --select -n --priority -h --backends attach -v --debug --no-keys -s --status -q --auto-update --nss logtime --logging-file get --exclude-backends search --target-version --version --due -f --outfile --export-session post --quiet --condition edit backends remove --save-responses ls --help --title"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobtracker boobtracker
_weboob_handjoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_handjoob handjoob
_weboob_translaboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update translate --nss --logging-file --exclude-backends --version --outfile --export-session --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_translaboob translaboob
_weboob_videoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd download --formatter nsfw --count --backends -e -d playlist -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss play --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_videoob videoob
_weboob_weboob_config_qt()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboob_config_qt weboob-config-qt
_weboob_flatboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="load help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_flatboob flatboob
_weboob_radioob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd download --formatter --count --backends -e -d playlist -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss play --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_radioob radioob
_weboob_qflatboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qflatboob qflatboob
_weboob_geolooc()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends --version --outfile --export-session --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_geolooc geolooc
_weboob_weboob_cli()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends --version --outfile --export-session --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboob_cli weboob-cli
_weboob_parceloob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss status --logging-file track --exclude-backends --version untrack --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_parceloob parceloob
_weboob_qhandjoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qhandjoob qhandjoob
_weboob_qcineoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qcineoob qcineoob
_weboob_boobmsg()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-E export_all help --insecure show export_thread -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -t -v --debug --no-keys -s -q --auto-update --nss status --logging-file --exclude-backends --version photos profile --outfile --export-session post --quiet --condition --accept-empty list --save-responses ls --help --title"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobmsg boobmsg
_weboob_shopoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends orders -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends --version --outfile --export-session --quiet --condition items payments --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_shopoob shopoob
_weboob_boobill()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd download --formatter --count --backends -e -d -f -a details -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss profile --logging-file subscriptions --exclude-backends --version download_pdf --outfile --export-session --quiet --condition bills documents --save-responses ls balance --help history"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobill boobill
_weboob_qcookboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qcookboob qcookboob
_weboob_boobcoming()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="load help --insecure attends -O -I --verbose cd --formatter export --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session unattends info --quiet --condition list --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobcoming boobcoming
_weboob_cineoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="getfile_subtitle info_movie help --insecure persons_in_common -O -I --verbose cd search_subtitle --formatter --count info_subtitle --backends search_torrent biography search_movie -e -d -f -a releases -c -b backends --select -n --no-header -h -v --debug --no-keys -s search_person -q --auto-update info_torrent search_movie_subtitle --nss casting --logging-file movies_in_common --exclude-backends --version filmography --outfile --export-session search_movie_torrent info_person --quiet --condition getfile_torrent --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_cineoob cineoob
_weboob_pastoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-E get_bin --max-age help --insecure post_bin -O -I --verbose cd --formatter --count --backends --no-keys --encoding -e -d -f -a -c -b -m backends --select -n --no-header -h -t -v --debug -p -s -q --auto-update --nss --logging-file get --exclude-backends --version --outfile --export-session post info --quiet --condition --public --save-responses ls --help --title"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_pastoob pastoob
_weboob_boobsize()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter last_sensor_measure --count --backends -e -d -f -a details -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session --quiet --condition --save-responses ls --help history"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobsize boobsize
_weboob_boobooks()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss rented --logging-file --exclude-backends search --version --outfile --export-session --quiet --condition renew --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boobooks boobooks
_weboob_comparoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends --version --outfile --export-session prices info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_comparoob comparoob
_weboob_boomoney()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-D -F -A help --insecure --parallel -O -N -I --verbose advisor cd --account --formatter -P --count --backends investment --noimport -e -d -f -a recipients -c -b transfer --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --force --logging-file --display --exclude-backends --version pocket budgea profile --outfile --export-session --quiet --condition backends list coming --save-responses ls add_recipient --help history"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_boomoney boomoney
_weboob_qboobtracker()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qboobtracker qboobtracker
_weboob_cookboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter export --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_cookboob cookboob
_weboob_weboorrents()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count getfile --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file --exclude-backends search --version --outfile --export-session info --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboorrents weboorrents
_weboob_qvideoob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qvideoob qvideoob
_weboob_weboob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --auto-update --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_weboob weboob
_weboob_booblyrics()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="help --insecure -O -I --verbose cd --formatter --count --backends -e -d -f -a -c -b backends --select -n --no-header -h -v --debug --no-keys -s -q --auto-update --nss --logging-file get --exclude-backends search --version --outfile --export-session --quiet --condition --save-responses ls --help"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_booblyrics booblyrics
_weboob_qgalleroob()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-e -d -a --logging-file --insecure -b -I --quiet --exclude-backends -h --version -v --debug --save-responses --export-session --verbose -q --backends --help --nss"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_qgalleroob qgalleroob
_weboob_havedate()
{
local cur args
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
args="-E export_all help --insecure show export_thread -O -I --verbose cd --formatter --count query --backends -e -d -f -a -c -b backends --select -n --no-header -h -t -v --debug --no-keys -s -q --auto-update events --nss profile --logging-file optim --exclude-backends --version photos --outfile --export-session post --quiet --condition --accept-empty list status --save-responses ls --help --title"
COMPREPLY=( $(compgen -o default -W "${args}" -- "$cur" ) )
}
complete -F _weboob_havedate havedate
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/weboob_lint.py 0000775 0000000 0000000 00000003052 13507732170 0024431 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
from __future__ import print_function
import logging
import os
import sys
from weboob.core import Weboob
# Hint: use this script with file:///path/to/local/modules/ in sources.list
# if you want to correctly check all modules.
logging.basicConfig()
weboob = Weboob()
weboob.modules_loader.load_all()
modules_without_tests = []
modules_without_icons = []
modules_without_py3 = []
with open(os.path.join(os.path.dirname(__file__), 'py3-compatible.modules')) as p:
modules_py3_compatible = [m.strip()
for m in p.readlines()
if not m.startswith('#')]
for name, module in weboob.modules_loader.loaded.items():
path = module.package.__path__[0]
if not os.path.exists(os.path.join(path, 'test.py')):
modules_without_tests.append(name)
if not os.path.exists(os.path.join(path, 'favicon.png')) and \
not os.path.exists(os.path.join(weboob.repositories.icons_dir, '%s.png' % name)) and \
not module.icon:
modules_without_icons.append(name)
if name not in modules_py3_compatible:
modules_without_py3.append(name)
if modules_without_tests:
print('\nModules without tests: %s' % ', '.join(sorted(modules_without_tests)))
if modules_without_icons:
print('\nModules without icons: %s' % ', '.join(sorted(modules_without_icons)))
if modules_without_py3:
print('\nModules for Python 2 only: %s' % ', '.join(sorted(modules_without_py3)))
if modules_without_tests or modules_without_icons or modules_without_py3:
sys.exit(1)
woob-ef0182519846a82abb51539df07730e9e01be395-tools/tools/weboob_lint.sh 0000775 0000000 0000000 00000001323 13507732170 0024412 0 ustar 00root root 0000000 0000000 #!/bin/sh
# stop on failure
set -e
. "$(dirname $0)/common.sh"
[ -z "${TMPDIR}" ] && TMPDIR="/tmp"
# do not allow undefined variables anymore
set -u
WEBOOB_TMPDIR=$(mktemp -d "${TMPDIR}/weboob_lint.XXXXXX")
# path to sources
WEBOOB_DIR=$(cd $(dirname $0)/.. && pwd -P)
touch "${WEBOOB_TMPDIR}/backends"
chmod 600 "${WEBOOB_TMPDIR}/backends"
echo "file://$WEBOOB_DIR/modules" > "${WEBOOB_TMPDIR}/sources.list"
export WEBOOB_WORKDIR="${WEBOOB_TMPDIR}"
export WEBOOB_DATADIR="${WEBOOB_TMPDIR}"
export PYTHONPATH="${WEBOOB_DIR}"
$PYTHON "${WEBOOB_DIR}/scripts/weboob-config" update
$PYTHON "${WEBOOB_DIR}/tools/weboob_lint.py"
# allow failing commands past this point
STATUS=$?
rm -rf "${WEBOOB_TMPDIR}"
exit $STATUS