From 84bbd6a82eea86c25dd017f173c1b849b96d85a8 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 13 Sep 2013 13:33:04 +0300 Subject: [PATCH] TransRead: improve user experience This patch solves the following problem. 1. I forgot to define the proxy. 2. I run bmaptool, it blocks, and several minutes later it fails with an error like "Connection timed out" I would instead like it to tell me that something is going wrong much earlier, why should I wait for several minutes? This patch improves the way we open URLs. Now instead of using the default (usually long) timeout, we first try with a short timeout, and if we cannot open the URL, we print user a warning, and then try to open with the default timeout. The user may press Ctrl-C once he/she sees the warning, or start checking the connectivity. Change-Id: Ia5f387de62574d84d914c21794f782b1b41d530f Signed-off-by: Artem Bityutskiy --- bmaptools/TransRead.py | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/bmaptools/TransRead.py b/bmaptools/TransRead.py index 49c7b59..9bf4e34 100644 --- a/bmaptools/TransRead.py +++ b/bmaptools/TransRead.py @@ -439,8 +439,17 @@ class TransRead: Open an URL 'url' and return the file-like object of the opened URL. """ + def _print_warning(logger, timeout): + """ + This is a small helper function for printing a warning if we cannot + open the URL for some time. + """ + logger.warning("failed to open the URL with %d sec timeout, is the " + "proxy setup correctly? Keep trying..." % timeout) + import urllib2 import httplib + import socket parsed_url = urlparse.urlparse(url) username = parsed_url.username @@ -473,15 +482,35 @@ class TransRead: opener.addheaders = [('User-Agent', 'Mozilla/5.0')] urllib2.install_opener(opener) - try: - f_obj = opener.open(url) - except urllib2.URLError as err: - raise Error("cannot open URL '%s': %s" % (url, err)) - except (IOError, ValueError, httplib.InvalidURL) as err: - raise Error("cannot open URL '%s': %s" % (url, err)) - except httplib.BadStatusLine: - raise Error("cannot open URL '%s': server responds with an HTTP " - "status code that we don't understand" % url) + # Open the URL. First try with a short timeout, and print a message + # which should supposedly give the a clue that something may be going + # wrong. + # The overall purpose of this is to improve user experience. For + # example, if one tries to open a file but did not setup the proxy + # environment variables propely, there will be a very long delay before + # the failure message. And it is much nicer to pre-warn the user early + # about something possibly being wrong. + for timeout in (10, None): + try: + f_obj = opener.open(url, timeout = timeout) + # Handling the timeout case in Python 2.7 + except socket.timeout, err: + if timeout is not None: + _print_warning(self._logger, timeout) + else: + raise Error("cannot open URL '%s': %s" % (url, err)) + except urllib2.URLError as err: + # Handling the timeout case in Python 2.6 + if timeout is not None and \ + isinstance(err.reason, socket.timeout): + _print_warning(self._logger, timeout) + else: + raise Error("cannot open URL '%s': %s" % (url, err)) + except (IOError, ValueError, httplib.InvalidURL) as err: + raise Error("cannot open URL '%s': %s" % (url, err)) + except httplib.BadStatusLine: + raise Error("cannot open URL '%s': server responds with an " + "HTTP status code that we don't understand" % url) self.is_url = True self._f_objs.append(f_obj) -- 2.7.4