Do not import exceptions of requests / load browser if needed

The import process of requests is very expensive: it imports all urllib,
and a lot of stuff. It is a problem on slow hardware, for applications
not running browser2 (example: weboob-config update).

This patch has two mains parts:
 * introduces load_browser to load a browser only if needed (a lot of repository
   processing does not need a browser)
 * Do not import exceptions of requests, but use Weboob internals one

Before: 6455 open/190 modules imported
After: 3997 open/112 modules
This commit is contained in:
Florent 2014-07-08 20:04:43 +02:00
commit 0e3e32adb1

View file

@ -20,25 +20,21 @@
from __future__ import print_function from __future__ import print_function
import imp import imp
import tarfile
import posixpath import posixpath
import shutil import shutil
import re import re
import sys import sys
import os import os
import subprocess import subprocess
import hashlib
from tempfile import NamedTemporaryFile
from datetime import datetime from datetime import datetime
from contextlib import closing from contextlib import closing
from compileall import compile_dir from compileall import compile_dir
from io import BytesIO from io import BytesIO
from weboob.tools.exceptions import BrowserHTTPError
from .modules import Module from .modules import Module
from weboob.tools.log import getLogger from weboob.tools.log import getLogger
from weboob.tools.misc import to_unicode from weboob.tools.misc import to_unicode
from weboob.tools.browser2.browser import BaseBrowser, Weboob as WeboobProfile
from requests.exceptions import HTTPError
try: try:
from ConfigParser import RawConfigParser, DEFAULTSECT from ConfigParser import RawConfigParser, DEFAULTSECT
except ImportError: except ImportError:
@ -175,7 +171,7 @@ class Repository(object):
# This is a remote repository, download file # This is a remote repository, download file
try: try:
fp = BytesIO(browser.open(posixpath.join(self.url, self.INDEX)).content) fp = BytesIO(browser.open(posixpath.join(self.url, self.INDEX)).content)
except HTTPError as e: except BrowserHTTPError as e:
raise RepositoryUnavailable(unicode(e)) raise RepositoryUnavailable(unicode(e))
self.parse_index(fp) self.parse_index(fp)
@ -204,7 +200,7 @@ class Repository(object):
try: try:
keyring_data = browser.open(posixpath.join(self.url, self.KEYRING)).content keyring_data = browser.open(posixpath.join(self.url, self.KEYRING)).content
sig_data = browser.open(posixpath.join(self.url, self.KEYRING + '.sig')).content sig_data = browser.open(posixpath.join(self.url, self.KEYRING + '.sig')).content
except HTTPError as e: except BrowserHTTPError as e:
raise RepositoryUnavailable(unicode(e)) raise RepositoryUnavailable(unicode(e))
if keyring.exists(): if keyring.exists():
if not keyring.is_valid(keyring_data, sig_data): if not keyring.is_valid(keyring_data, sig_data):
@ -418,10 +414,7 @@ class Repositories(object):
self.logger = getLogger('repositories') self.logger = getLogger('repositories')
self.version = version self.version = version
class WeboobBrowser(BaseBrowser): self.browser = None
PROFILE = WeboobProfile(version)
self.browser = WeboobBrowser()
self.workdir = workdir self.workdir = workdir
self.datadir = datadir self.datadir = datadir
@ -448,6 +441,13 @@ class Repositories(object):
else: else:
self.load() self.load()
def load_browser(self):
from weboob.tools.browser2.browser import BaseBrowser, Weboob as WeboobProfile
class WeboobBrowser(BaseBrowser):
PROFILE = WeboobProfile(self.version)
if self.browser is None:
self.browser = WeboobBrowser()
def create_dir(self, name): def create_dir(self, name):
if not os.path.exists(name): if not os.path.exists(name):
os.makedirs(name) os.makedirs(name)
@ -511,6 +511,7 @@ class Repositories(object):
""" """
Retrieve the icon of a module and save it in ~/.local/share/weboob/icons/. Retrieve the icon of a module and save it in ~/.local/share/weboob/icons/.
""" """
self.load_browser()
if not isinstance(module, ModuleInfo): if not isinstance(module, ModuleInfo):
module = self.get_module_info(module) module = self.get_module_info(module)
@ -528,7 +529,7 @@ class Repositories(object):
try: try:
icon = self.browser.open(icon_url) icon = self.browser.open(icon_url)
except HTTPError: except BrowserHTTPError:
pass # no icon, no problem pass # no icon, no problem
else: else:
with open(dest_path, 'wb') as fp: with open(dest_path, 'wb') as fp:
@ -545,6 +546,7 @@ class Repositories(object):
return l return l
def update_repositories(self, progress=IProgress()): def update_repositories(self, progress=IProgress()):
self.load_browser()
""" """
Update list of repositories by downloading them Update list of repositories by downloading them
and put them in ~/.local/share/weboob/repositories/. and put them in ~/.local/share/weboob/repositories/.
@ -628,6 +630,9 @@ class Repositories(object):
:param progress: observer object :param progress: observer object
:type progress: :class:`IProgress` :type progress: :class:`IProgress`
""" """
import tarfile
self.load_browser()
if isinstance(module, ModuleInfo): if isinstance(module, ModuleInfo):
info = module info = module
elif isinstance(module, basestring): elif isinstance(module, basestring):
@ -655,7 +660,7 @@ class Repositories(object):
progress.progress(0.2, 'Downloading module...') progress.progress(0.2, 'Downloading module...')
try: try:
tardata = self.browser.open(module.url).content tardata = self.browser.open(module.url).content
except HTTPError as e: except BrowserHTTPError as e:
raise ModuleInstallError('Unable to fetch module: %s' % e) raise ModuleInstallError('Unable to fetch module: %s' % e)
# Check signature # Check signature
@ -755,6 +760,7 @@ class Keyring(object):
data and sigdata should be strings. data and sigdata should be strings.
""" """
gpgv = self.find_gpgv() gpgv = self.find_gpgv()
from tempfile import NamedTemporaryFile
with NamedTemporaryFile(suffix='.sig') as sigfile: with NamedTemporaryFile(suffix='.sig') as sigfile:
sigfile.write(sigdata) sigfile.write(sigdata)
sigfile.flush() # very important sigfile.flush() # very important
@ -777,6 +783,7 @@ class Keyring(object):
def __str__(self): def __str__(self):
if self.exists(): if self.exists():
with open(self.vpath, 'r') as f: with open(self.vpath, 'r') as f:
import hashlib
h = hashlib.sha1(f.read()).hexdigest() h = hashlib.sha1(f.read()).hexdigest()
return 'Keyring version %s, checksum %s' % (self.version, h) return 'Keyring version %s, checksum %s' % (self.version, h)
return 'NO KEYRING' return 'NO KEYRING'