Skip to content

Commit 16da483

Browse files
committed
byterun/modules.py: Ensure that modules go through byterun
1 parent a07642f commit 16da483

File tree

3 files changed

+91
-5
lines changed

3 files changed

+91
-5
lines changed

byterun/modules.py

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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+

byterun/pyobj.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ def __init__(self, f_code, f_globals, f_locals, f_closure, f_back):
151151
if f_back:
152152
self.f_builtins = f_back.f_builtins
153153
else:
154-
self.f_builtins = f_locals['__builtins__']
154+
if hasattr(f_locals, '__builtins__'):
155+
self.f_builtins = f_locals['__builtins__']
156+
else:
157+
self.f_builtins = f_globals['__builtins__']
155158
if hasattr(self.f_builtins, '__dict__'):
156159
self.f_builtins = self.f_builtins.__dict__
157160

byterun/pyvm2.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
PY3, PY2 = six.PY3, not six.PY3
1818

1919
from .pyobj import Frame, Block, Method, Function, Generator, Cell
20+
from .modules import import_python_module
2021

2122
log = logging.getLogger(__name__)
2223

@@ -1105,6 +1106,11 @@ def call_function(self, arg, args, kwargs):
11051106
retval = func(*posargs, **namedargs)
11061107
self.push(retval)
11071108

1109+
def import_module(self, m, fromList, level):
1110+
f = self.frame
1111+
res = import_python_module(m, f.f_globals, f.f_locals, fromList, level)
1112+
self.push(res)
1113+
11081114
def byte_RETURN_VALUE(self):
11091115
self.return_value = self.pop()
11101116
if self.frame.generator:
@@ -1141,10 +1147,7 @@ def byte_YIELD_FROM(self):
11411147

11421148
def byte_IMPORT_NAME(self, name):
11431149
level, fromlist = self.popn(2)
1144-
frame = self.frame
1145-
self.push(
1146-
__import__(name, frame.f_globals, frame.f_locals, fromlist, level)
1147-
)
1150+
self.import_module(name, fromlist, level)
11481151

11491152
def byte_IMPORT_STAR(self):
11501153
# TODO: this doesn't use __all__ properly.

0 commit comments

Comments
 (0)