From 5c1b00a03221f55ac48b0d34030160cf55b4225f Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Tue, 5 Oct 2010 08:10:02 -0500 Subject: proxy support: degrade gracefully when socket.socket is unavailable This should allow httplib2 to continue to work even on platforms like appengine where the socket module exists but has no socket attribute. --- python2/httplib2/__init__.py | 11 +++++++++-- python2/httplib2/socks.py | 4 ++++ python2/httplib2/test/brokensocket/socket.py | 1 + python2/httplib2/test/test_no_socket.py | 24 ++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 python2/httplib2/test/brokensocket/socket.py create mode 100644 python2/httplib2/test/test_no_socket.py (limited to 'python2') diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py index c886049..567e24e 100644 --- a/python2/httplib2/__init__.py +++ b/python2/httplib2/__init__.py @@ -54,7 +54,10 @@ import hmac from gettext import gettext as _ import socket -from httplib2 import socks +try: + from httplib2 import socks +except ImportError: + socks = None # Build the appropriate socket wrapper for ssl try: @@ -80,7 +83,7 @@ def has_timeout(timeout): # python 2.6 __all__ = ['Http', 'Response', 'ProxyInfo', 'HttpLib2Error', 'RedirectMissingLocation', 'RedirectLimit', 'FailedToDecompressContent', 'UnimplementedDigestAuthOptionError', 'UnimplementedHmacDigestAuthOptionError', - 'debuglevel'] + 'debuglevel', 'ProxiesUnavailableError'] # The httplib debug level, set to a non-zero value to get debug output @@ -122,6 +125,7 @@ class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse): pass class RelativeURIError(HttpLib2Error): pass class ServerNotFoundError(HttpLib2Error): pass +class ProxiesUnavailableError(HttpLib2Error): pass # Open Items: # ----------- @@ -718,6 +722,9 @@ class HTTPConnectionWithTimeout(httplib.HTTPConnection): def connect(self): """Connect to the host and port specified in __init__.""" # Mostly verbatim from httplib.py. + if self.proxy_info and socks is None: + raise ProxiesUnavailableError( + 'Proxy support missing but proxy use was requested!') msg = "getaddrinfo returns an empty list" for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): diff --git a/python2/httplib2/socks.py b/python2/httplib2/socks.py index 2bddd7a..b65fb38 100644 --- a/python2/httplib2/socks.py +++ b/python2/httplib2/socks.py @@ -41,6 +41,10 @@ mainly to merge bug fixes found in Sourceforge """ import socket + +if getattr(socket, 'socket', None) is None: + raise ImportError('socket.socket missing, proxy support unusable') + import struct import sys diff --git a/python2/httplib2/test/brokensocket/socket.py b/python2/httplib2/test/brokensocket/socket.py new file mode 100644 index 0000000..ff7c0b7 --- /dev/null +++ b/python2/httplib2/test/brokensocket/socket.py @@ -0,0 +1 @@ +from realsocket import gaierror, error, getaddrinfo, SOCK_STREAM diff --git a/python2/httplib2/test/test_no_socket.py b/python2/httplib2/test/test_no_socket.py new file mode 100644 index 0000000..66ba056 --- /dev/null +++ b/python2/httplib2/test/test_no_socket.py @@ -0,0 +1,24 @@ +"""Tests for httplib2 when the socket module is missing. + +This helps ensure compatibility with environments such as AppEngine. +""" +import os +import sys +import unittest + +import httplib2 + +class MissingSocketTest(unittest.TestCase): + def setUp(self): + self._oldsocks = httplib2.socks + httplib2.socks = None + + def tearDown(self): + httplib2.socks = self._oldsocks + + def testProxyDisabled(self): + proxy_info = httplib2.ProxyInfo('blah', + 'localhost', 0) + client = httplib2.Http(proxy_info=proxy_info) + self.assertRaises(httplib2.ProxiesUnavailableError, + client.request, 'http://localhost:-1/') -- cgit v1.2.1