Skip to content

Instantly share code, notes, and snippets.

Created January 14, 2015 16:26
What would you like to do?
Overriding stdlib http package
import sys
from importlib import invalidate_caches
from import MetaPathFinder
from importlib.machinery import ModuleSpec, SourceFileLoader
from os.path import dirname, join, abspath, isdir, isfile
class Finder(MetaPathFinder):
def find_spec(self, fullname, path, target=None):
name_parts = fullname.split('.')
if name_parts[0] != 'http':
# don't worry about non-http modules
name_parts[0] = 'httplib3'
find_path = abspath(join(*name_parts))
if isdir(find_path):
origin = join(find_path, '')
origin = '{}.py'.format(find_path)
if not isfile(origin):
# assume it's a module attribute
loader = SourceFileLoader(fullname, origin)
is_package = loader.is_package(fullname)
spec = ModuleSpec(
fullname, loader, is_package=is_package, origin=origin)
if is_package:
spec.submodule_search_locations = [dirname(__file__)]
return spec
def inject():
for k in [k for k in sys.modules.keys() if k.startswith('http')]:
del sys.modules[k]
sys.meta_path.insert(0, Finder())
Copy link

Do you really want to delete all already-loaded modules that start with 'http'? How about just a whitelist of names and prefixes (if necessary)? If someone tries to use their "httputils" module they might be surprised. There are 58 distributions on pypi that start with "http":

$ curl -s '' | grep pypi/http | wc

$ curl -s '' | grep pypi/http | head -5
 <td><a href="/pypi/http/0.02">http&nbsp;0.02</a></td>
 <td><a href="/pypi/http1/0.3.1">http1&nbsp;0.3.1</a></td>
 <td><a href="/pypi/http2/0.0.0-dev">http2&nbsp;0.0.0-dev</a></td>
 <td><a href="/pypi/httpagentparser/1.7.6">httpagentparser&nbsp;1.7.6</a></td>
 <td><a href="/pypi/httpappengine/0.1.9">httpappengine&nbsp;0.1.9</a></td>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment