Skip to content

Commit 7bbec19

Browse files
committed
byterun/modules.py: Ensure that modules go through byterun
1 parent 5fce7b9 commit 7bbec19

File tree

2 files changed

+97
-5
lines changed

2 files changed

+97
-5
lines changed

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

+93-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
import sys
1212
import types
1313

14+
import os.path
15+
import imp
16+
NoSource = Exception
17+
Loaded = {}
18+
19+
1420
import six
1521
from six.moves import reprlib
1622

@@ -1109,6 +1115,44 @@ def call_function(self, arg, args, kwargs):
11091115
retval = func(*posargs, **namedargs)
11101116
self.push(retval)
11111117

1118+
def import_module(self, m, fromList, level):
1119+
f = self.frame
1120+
res = self.import_python_module(m, f.f_globals, f.f_locals, fromList, level)
1121+
self.push(res)
1122+
1123+
def import_python_module(self, modulename, glo, loc, fromlist, level, search=None):
1124+
"""Import a python module.
1125+
`modulename` is the name of the module, possibly a dot-separated name.
1126+
`fromlist` is the list of things to imported from the module.
1127+
"""
1128+
try:
1129+
if '.' not in modulename:
1130+
mymod = find_module(modulename, search, level, True, glo, loc)
1131+
# Open the source file.
1132+
try:
1133+
with open(mymod.__file__, "rU") as source_file:
1134+
source = source_file.read()
1135+
if not source or source[-1] != '\n': source += '\n'
1136+
code = compile(source, mymod.__file__, "exec")
1137+
# Execute the source file.
1138+
self.run_code(code, f_globals=mymod.__dict__, f_locals=mymod.__dict__)
1139+
# strip it with fromlist
1140+
# get the defined module
1141+
return mymod
1142+
except IOError as e:
1143+
raise NoSource("module does not live in a file: %r" % modulename)
1144+
else:
1145+
pkgn, name = modulename.rsplit('.', 1)
1146+
pkg = find_module(pkgn, search, level, False, glo, loc)
1147+
mod = self.import_python_module(name, glo, loc, fromlist, level, pkg.__file__)
1148+
# mod is an attribute of pkg
1149+
setattr(pkg, mod.__name__, mod)
1150+
return pkg
1151+
except NoSource as e:
1152+
m = __import__(modulename, glo, loc, fromlist, level)
1153+
Loaded[modulename] = m
1154+
return m
1155+
11121156
def byte_RETURN_VALUE(self):
11131157
self.return_value = self.pop()
11141158
if self.frame.generator:
@@ -1145,10 +1189,7 @@ def byte_YIELD_FROM(self):
11451189

11461190
def byte_IMPORT_NAME(self, name):
11471191
level, fromlist = self.popn(2)
1148-
frame = self.frame
1149-
self.push(
1150-
__import__(name, frame.f_globals, frame.f_locals, fromlist, level)
1151-
)
1192+
self.import_module(name, fromlist, level)
11521193

11531194
def byte_IMPORT_STAR(self):
11541195
# TODO: this doesn't use __all__ properly.
@@ -1232,3 +1273,51 @@ def calculate_metaclass(metaclass, bases):
12321273
elif not issubclass(winner, t):
12331274
raise TypeError("metaclass conflict", winner, t)
12341275
return winner
1276+
1277+
1278+
1279+
def find_module_absolute(name, searchpath, isfile):
1280+
# search path should really be appeneded to a list of paths
1281+
# that the interpreter knows about. For now, we only look in '.'
1282+
myname = name if not searchpath else "%s/%s" % (searchpath, name)
1283+
if isfile:
1284+
fname = "%s.py" % myname
1285+
return os.path.abspath(fname) if os.path.isfile(fname) else None
1286+
else:
1287+
return os.path.abspath(myname) if os.path.isdir(myname) else None
1288+
1289+
def find_module_relative(name, searchpath): return None
1290+
1291+
def find_module(name, searchpath, level, isfile=True, glo=None, loc=None):
1292+
"""
1293+
`level` specifies whether to use absolute and/or relative.
1294+
The default is -1 which is both absolute and relative
1295+
0 means only absolute and positive values indicate number
1296+
parent directories to search relative to the directory of module
1297+
calling `__import__`
1298+
"""
1299+
if name in Loaded: return Loaded[name]
1300+
1301+
assert level <= 0 # we dont implement relative yet
1302+
path = None
1303+
if level == 0:
1304+
path = find_module_absolute(name, searchpath, isfile)
1305+
elif level > 0:
1306+
path = find_module_relative(name, searchpath, isfile)
1307+
else:
1308+
res = find_module_absolute(name, searchpath, isfile)
1309+
path = find_module_relative(name, searchpath, isfile) if not res \
1310+
else res
1311+
1312+
if not path:
1313+
v = imp.find_module(name, searchpath)
1314+
if v and v[1]:
1315+
path = v[1]
1316+
else:
1317+
raise NoSource("<%s> was not found" % name)
1318+
mymod = types.ModuleType(name)
1319+
mymod.__file__ = path
1320+
mymod.__builtins__ = glo['__builtins__']
1321+
# mark the module as being loaded
1322+
Loaded[name] = mymod
1323+
return mymod

0 commit comments

Comments
 (0)