""" virtualenv installs a wrapper for the real distutils into the virtual environment. Ignore that wrapper, but go for the real distutils instead This recipe is rather compilicated and definitely not a good model for other recipes!!! """ from __future__ import absolute_import import sys, os, imp from modulegraph.modulegraph import MissingModule, \ Package, SourceModule, CompiledModule, find_module def retry_import(mf, m): """ Try to reimport 'm', which should be a MissingModule """ if '.' in m.identifier: pname, partname = m.identifier.rsplit('.', 1) parent = mf.findNode(pname) else: parent = None partname = m.identifier # This is basicly mf.find_module inlined and with a # check disabled. def fmod(name, path, parent): if path is None: if name in sys.builtin_module_names: return (None, None, ("", "", imp.C_BUILTIN)) path = mf.path fp, buf, stuff = find_module(name, path) if buf: buf = os.path.realpath(buf) return (fp, buf, stuff) try: fp, pathname, stuff = fmod(partname, parent and parent.packagepath, parent) except ImportError as e: return if stuff[-1] == imp.PKG_DIRECTORY: m.__class__ = Package elif stuff[-1] == imp.PY_SOURCE: m.__class__ = SourceModule else: m.__class__ = CompiledModule #making this match the code later on that checks whether scan_code needs a leading _ if hasattr(mf, 'load_module'): m = mf.load_module(m.identifier, fp, pathname, stuff) else: m = mf._load_module(m.identifier, fp, pathname, stuff) if parent: mf.createReference(m, parent) parent[partname] = m return m def check(cmd, mf): m = mf.findNode('distutils') if m is None or m.filename is None: return None with open(m.filename, 'rU') as fp: contents = fp.read() if 'virtualenv' in contents: # This is the virtualenv version mos = mf.findNode('os') if mos is None or mos.filename is None: raise ValueError("Where is the os module") m.filename = os.path.join(os.path.dirname(mos.filename), 'distutils', '__init__.py') with open(m.filename) as fp: source = fp.read() + '\n' m.code = co = compile(source, m.filename, 'exec') m.packagepath = [os.path.dirname(m.filename)] if mf.replace_paths: co = mf.replace_paths_in_code(co) # XXX: Recent versions of modulegraph made scan_code private, # temporarily call the private version. if hasattr(mf, 'scan_code'): mf.scan_code(co, m) else: mf._scan_code(co, m) # That's not all there is to this, we need to look for # MissingModules in the distutils namespace as well and # try to import these again. for m in mf.flatten(): if isinstance(m, MissingModule): if m.identifier.startswith('distutils.'): # A missing distutils package, retry # importing it. # retry_import(mf, m) return dict()