diff --git a/oauth2client/crypt.py b/oauth2client/crypt.py index ccdda8c54..19f9d9f32 100644 --- a/oauth2client/crypt.py +++ b/oauth2client/crypt.py @@ -38,8 +38,33 @@ class AppIdentityError(Exception): pass +def _TryOpenSslImport(): + """Import OpenSSL, avoiding the explicit import where possible. + + Importing OpenSSL 0.14 can take up to 0.5s, which is a large price + to pay at module import time. However, it's also possible for + ``imp.find_module`` to fail to find the module, even when it's + installed. (This is the case in various exotic environments, + including some relevant for Google.) So we first try a fast-path, + and fall back to the slow import as needed. + + Args: + None + Returns: + None + Raises: + ImportError if OpenSSL is unavailable. + + """ + try: + _ = imp.find_module('OpenSSL') + return + except ImportError: + import OpenSSL + + try: - _ = imp.find_module('OpenSSL') + _TryOpenSslImport() class OpenSSLVerifier(object): """Verifies the signature on a message.""" diff --git a/tests/test_crypt.py b/tests/test_crypt.py index 74c25b6f2..10fff0415 100644 --- a/tests/test_crypt.py +++ b/tests/test_crypt.py @@ -60,15 +60,22 @@ def test_succeeds(self): def test_without_openssl(self): import imp imp_find_module = imp.find_module + orig_sys_path = sys.path def find_module(module_name): raise ImportError('No module named %s' % module_name) try: + for m in list(sys.modules): + if m.startswith('OpenSSL'): + sys.modules.pop(m) + sys.path = [] imp.find_module = find_module reload(crypt) self.assertRaises(NotImplementedError, crypt.pkcs12_key_as_pem, 'FOO', 'BAR') finally: + sys.path = orig_sys_path imp.find_module = imp_find_module + import OpenSSL reload(crypt) def test_with_nonsense_key(self):