From 6ea3f2ada87177559188bfc9148af1b2384f38c6 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sat, 28 Feb 2015 20:13:45 -0600 Subject: [PATCH 1/3] Only alias the imports for vendored dependencies While discussion the issue, Donald Stufft (@dstufft) and I realized the simplest solution is to simply add an alias per vendored dependency. The resulting changes are simple and effective. It prevents the issue in 2.5.2 and 2.5.3 where the following would work: from requests.packages import webbrowser This now appropriately raises an ImportError. Closes #2465 --- requests/packages/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/requests/packages/__init__.py b/requests/packages/__init__.py index ec6a9e06..7b2a0913 100644 --- a/requests/packages/__init__.py +++ b/requests/packages/__init__.py @@ -27,9 +27,10 @@ import sys class VendorAlias(object): - def __init__(self): + def __init__(self, package_name): + self._package_name = package_name self._vendor_name = __name__ - self._vendor_pkg = self._vendor_name + "." + self._vendor_pkg = self._vendor_name + "." + self._package_name def find_module(self, fullname, path=None): if fullname.startswith(self._vendor_pkg): @@ -92,4 +93,4 @@ class VendorAlias(object): return module -sys.meta_path.append(VendorAlias()) +sys.meta_path.extend([VendorAlias("urllib3"), VendorAlias("chardet")]) From 9d8a57f2a29de97682d85d71ea98354ac8223442 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sat, 28 Feb 2015 20:19:13 -0600 Subject: [PATCH 2/3] Add a test to ensure the alias does not regress --- test_requests.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test_requests.py b/test_requests.py index 6e527848..57f39a62 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1598,5 +1598,12 @@ def test_urllib3_retries(): with pytest.raises(RetryError): s.get(httpbin('status/500')) +def test_vendor_aliases(): + from requests.packages import urllib3 + from requests.packages import chardet + + with pytest.raises(ImportError): + from requests.packages import webbrowser + if __name__ == '__main__': unittest.main() From 2669f0c0b1e98c9ea36d2614d48b07ad150ea276 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sat, 28 Feb 2015 23:04:22 -0600 Subject: [PATCH 3/3] Fix when packages are unvendored When working these changes back upstream to pip, we realized that the previous fix wasn't ideal since unvendoring the packages broke the imports. For example, if urllib3 were unvendored, then the following would fail: from requests.packages import urllib3 --- requests/packages/__init__.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/requests/packages/__init__.py b/requests/packages/__init__.py index 7b2a0913..4dcf870f 100644 --- a/requests/packages/__init__.py +++ b/requests/packages/__init__.py @@ -27,10 +27,13 @@ import sys class VendorAlias(object): - def __init__(self, package_name): - self._package_name = package_name + def __init__(self, package_names): + self._package_names = package_names self._vendor_name = __name__ - self._vendor_pkg = self._vendor_name + "." + self._package_name + self._vendor_pkg = self._vendor_name + "." + self._vendor_pkgs = [ + self._vendor_pkg + name for name in self._package_names + ] def find_module(self, fullname, path=None): if fullname.startswith(self._vendor_pkg): @@ -45,6 +48,14 @@ class VendorAlias(object): ) ) + if not (name == self._vendor_name or + any(name.startswith(pkg) for pkg in self._vendor_pkgs)): + raise ImportError( + "Cannot import %s, must be one of %s." % ( + name, self._vendor_pkgs + ) + ) + # Check to see if we already have this item in sys.modules, if we do # then simply return that. if name in sys.modules: @@ -93,4 +104,4 @@ class VendorAlias(object): return module -sys.meta_path.extend([VendorAlias("urllib3"), VendorAlias("chardet")]) +sys.meta_path.append(VendorAlias(["urllib3", "chardet"]))