weboob 6.6 KB
Newer Older
1 2 3 4 5
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai


6
# Copyright(C) 2009-2017  Romain Bignon
7 8 9 10
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU Lesser General Public License as published by
12 13 14 15 16 17
# 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
18
# GNU Lesser General Public License for more details.
19
#
20
# You should have received a copy of the GNU Lesser General Public License
21 22
# along with weboob. If not, see <http://www.gnu.org/licenses/>.

23
from __future__ import absolute_import
ntome's avatar
ntome committed
24
from __future__ import print_function
25

26
import inspect
27
import os
28
import re
29
import sys
ntome's avatar
ntome committed
30
from collections import OrderedDict
31
from datetime import datetime, timedelta
32 33 34 35 36

import weboob.applications

from weboob.tools.application.console import ConsoleApplication

37 38 39 40 41 42
try:
    from weboob.tools.application.qt5 import QtApplication
except ImportError:
    class QtApplication(object):
        pass

43

44 45 46
__all__ = ['Weboob']


47
class Weboob(ConsoleApplication):
48
    APPNAME = 'weboob'
49
    VERSION = '1.4'
50 51 52
    COPYRIGHT = 'Copyright(C) 2010-YEAR The Weboob Team'
    DESCRIPTION = "This is a console script to launch weboob applications,"
    SHORT_DESCRIPTION = "launch weboob applications"
53 54 55

    UPDATE_DAYS_DELAY = 20

56
    def main(self):
57 58 59
        interactive = sys.stdout.isatty()
        if interactive:
            self.update()
60 61 62 63

        capApplicationDict = self.init_CapApplicationDict()

        if len(sys.argv) >= 2:
64 65 66 67 68 69 70 71
            try:
                cmd = getattr(self, 'cmd_%s' % sys.argv[1])
            except AttributeError:
                pass
            else:
                cmd()
                return

72 73
            cap = sys.argv.pop(1)
            if cap not in capApplicationDict:
74 75 76 77 78
                if interactive:
                    print('Unknown capability, please choose one in the following list')
                    cap = self.choose_capability(capApplicationDict)
                else:
                    cap = None
79 80

        else:
81 82 83 84
            if interactive:
                cap = self.choose_capability(capApplicationDict)
            else:
                cap = None
85

86
        def appsortkey(app):
87 88
            if issubclass(app, QtApplication):
                return '1' + app.APPNAME
89
            else:
90
                return '0' + app.APPNAME
91

92 93 94 95 96 97 98 99
        if cap:
            applications = capApplicationDict[cap]
            applications = sorted(set(applications), key=appsortkey)
            application = applications[0] if len(applications) == 1 else self.choose_application(applications)

            application.run()
        else:
            print('Please provide a capability.')
100

101 102 103
    def cmd_update(self):
        self.weboob.update()

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    def update(self):
        for repository in self.weboob.repositories.repositories:
            update_date = datetime.strptime(str(repository.update), '%Y%m%d%H%M')
            if (datetime.now() - timedelta(days=self.UPDATE_DAYS_DELAY)) > update_date:
                update = self.ask('The repositories have not been updated for %s days, do you want to update them ? (y/n)'
                                  % self.UPDATE_DAYS_DELAY,
                                  default='n')
                if update.upper() == 'Y':
                    self.weboob.repositories.update()
                break

    def choose_application(self, applications):
        application = None
        while not application:
            for app in applications:
                print('  %s%2d)%s %s: %s' % (self.BOLD,
                                             applications.index(app) + 1,
                                             self.NC,
                                             app.APPNAME,
                                             app.DESCRIPTION))
            r = self.ask('  Select an application', regexp='(\d+|)', default='')
            if not r.isdigit():
                continue
            r = int(r)
            if r <= 0 or r > len(applications):
                continue
            application = applications[r - 1]
        return application

    def choose_capability(self, capApplicationDict):
        cap = None
135 136 137 138
        caps = list(capApplicationDict.keys())
        while cap not in caps:
            for n, _cap in enumerate(caps):
                print('  %s%2d)%s %s' % (self.BOLD, n + 1, self.NC, _cap))
139 140 141 142
            r = self.ask('  Select a capability', regexp='(\d+|)', default='')
            if not r.isdigit():
                continue
            r = int(r)
143
            if r <= 0 or r > len(caps):
144
                continue
145
            cap = caps[r - 1]
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
        return cap

    def init_CapApplicationDict(self):
        capApplicationDict = {}
        for path in weboob.applications.__path__:
            regexp = re.compile('^%s/([\w\d_]+)$' % path)
            for root, dirs, files in os.walk(path):
                m = regexp.match(root)
                if not (m and '__init__.py' in files):
                    continue

                application = self.get_applicaction_from_filename(m.group(1))
                if not application:
                    continue

                capabilities = self.get_application_capabilities(application)
                if not capabilities:
                    continue

                for capability in capabilities:
                    if capability in capApplicationDict:
                        capApplicationDict[capability].append(application)
                    else:
                        capApplicationDict[capability] = [application]

171
        return OrderedDict([(k, v) for k, v in sorted(capApplicationDict.items())])
172 173

    def get_application_capabilities(self, application):
Romain Bignon's avatar
Romain Bignon committed
174
        if hasattr(application, 'CAPS') and application.CAPS:
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
            _capabilities = list(application.CAPS) if isinstance(application.CAPS, tuple) else [application.CAPS]
            return [os.path.splitext(os.path.basename(inspect.getfile(x)))[0] for x in _capabilities]

    def get_applicaction_from_filename(self, name):
        module = 'weboob.applications.%s.%s' % (name, name)
        try:
            _module = __import__(module, fromlist=['*'])
        except ImportError:
            return

        _application = [x for x in dir(_module) if x.lower() == name]
        if _application:
            return getattr(_module, _application[0])


if __name__ == '__main__':
Romain Bignon's avatar
Romain Bignon committed
191
    try:
192
        Weboob().main()
Romain Bignon's avatar
Romain Bignon committed
193 194
    except KeyboardInterrupt:
        print('')