|
| 1 | +import os.path |
| 2 | +import types |
| 3 | +NoSource = Exception |
| 4 | + |
| 5 | +def find_module_absolute(name, searchpath, isfile): |
| 6 | + # search path should really be appeneded to a list of paths |
| 7 | + # that the interpreter knows about. For now, we only look in '.' |
| 8 | + myname = name if not searchpath else "%s/%s" % (searchpath, name) |
| 9 | + if isfile: |
| 10 | + fname = "%s.py" % myname |
| 11 | + return os.path.abspath(fname) if os.path.isfile(fname) else None |
| 12 | + else: |
| 13 | + return os.path.abspath(myname) if os.path.isdir(myname) else None |
| 14 | + |
| 15 | +def find_module_relative(name, searchpath): return None |
| 16 | + |
| 17 | +def find_module(name, searchpath, level, isfile=True): |
| 18 | + """ |
| 19 | + `level` specifies whether to use absolute and/or relative. |
| 20 | + The default is -1 which is both absolute and relative |
| 21 | + 0 means only absolute and positive values indicate number |
| 22 | + parent directories to search relative to the directory of module |
| 23 | + calling `__import__` |
| 24 | + """ |
| 25 | + assert level <= 0 # we dont implement relative yet |
| 26 | + if level == 0: |
| 27 | + return find_module_absolute(name, searchpath, isfile) |
| 28 | + elif level > 0: |
| 29 | + return find_module_relative(name, searchpath, isfile) |
| 30 | + else: |
| 31 | + res = find_module_absolute(name, searchpath, isfile) |
| 32 | + return find_module_relative(name, searchpath, isfile) if not res \ |
| 33 | + else res |
| 34 | + |
| 35 | +def import_python_dir(name, search, glo, loc, level): |
| 36 | + mymod = types.ModuleType(name) |
| 37 | + path = find_module(name, search, level, isfile=False) |
| 38 | + if path == None: raise NoSource("<%s> not a directory" % path) |
| 39 | + mymod.__file__ = path |
| 40 | + mymod.__path__ = path |
| 41 | + mymod.__builtins__ = glo['__builtins__'] |
| 42 | + return mymod |
| 43 | + |
| 44 | + |
| 45 | +def import_python_module(modulename, glo, loc, fromlist, level, search=None): |
| 46 | + """Import a python module. |
| 47 | + `modulename` is the name of the module, possibly a dot-separated name. |
| 48 | + `fromlist` is the list of things to imported from the module. |
| 49 | + """ |
| 50 | + try: |
| 51 | + if '.' not in modulename: |
| 52 | + pkg, name = None, modulename |
| 53 | + path = find_module(name, search, level, isfile=True) |
| 54 | + mymod = types.ModuleType(name) |
| 55 | + mymod.__file__ = path |
| 56 | + mymod.__builtins__ = glo['__builtins__'] |
| 57 | + # Open the source file. |
| 58 | + try: |
| 59 | + with open(path, "rU") as source_file: |
| 60 | + source = source_file.read() |
| 61 | + if not source or source[-1] != '\n': source += '\n' |
| 62 | + code = compile(source, path, "exec") |
| 63 | + # Execute the source file. |
| 64 | + vm = VirtualMachine() |
| 65 | + vm.run_code(code, f_globals=mymod.__dict__, f_locals=mymod.__dict__) |
| 66 | + # strip it with fromlist |
| 67 | + # get the defined module |
| 68 | + return mymod |
| 69 | + except IOError: |
| 70 | + raise NoSource("module does not live in a file: %r" % modulename) |
| 71 | + else: |
| 72 | + pkgn, name = modulename.rsplit('.', 1) |
| 73 | + pkg = import_python_dir(pkgn, search, glo, loc, level) |
| 74 | + mod = import_python_module(name, glo, loc, fromlist, level, pkg.__path__) |
| 75 | + # mod is an attribute of pkg |
| 76 | + setattr(pkg, mod.__name__, mod) |
| 77 | + return pkg |
| 78 | + except NoSource as e: |
| 79 | + return __import__(modulename, glo, loc, fromlist, level) |
| 80 | + |
0 commit comments