diff options
author | Guido van Rossum <guido@python.org> | 1995-08-07 20:19:27 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1995-08-07 20:19:27 (GMT) |
commit | 13833560390fec8ae5a09b634c6ea9fb5b4ffc51 (patch) | |
tree | 924dedcae14aa19ee20db29707c0f1ad419184e8 /Lib | |
parent | 221df24940595eb9d99d598e39fd2967050bee11 (diff) | |
download | cpython-13833560390fec8ae5a09b634c6ea9fb5b4ffc51.zip cpython-13833560390fec8ae5a09b634c6ea9fb5b4ffc51.tar.gz cpython-13833560390fec8ae5a09b634c6ea9fb5b4ffc51.tar.bz2 |
added sys.std files, read-only open, reload
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/rexec.py | 107 |
1 files changed, 104 insertions, 3 deletions
diff --git a/Lib/rexec.py b/Lib/rexec.py index 3f04391..316fc1c 100644 --- a/Lib/rexec.py +++ b/Lib/rexec.py @@ -11,6 +11,11 @@ available; this module provides a reasonable default, but derived classes can change the policies e.g. by overriding or extending class variables like ok_builtin_modules or methods like make_sys(). +XXX To do: +- r_open should allow writing tmp dir +- r_exec etc. with explicit globals/locals? (Use rexec("exec ... in ...")?) +- r_reload should reload from same location (that's one for ihooks?) + """ @@ -21,6 +26,39 @@ import marshal import ihooks +class FileBase: + + ok_file_methods = ('fileno', 'flush', 'isatty', 'read', 'readline', + 'readlines', 'seek', 'tell', 'write', 'writelines') + + +class FileWrapper(FileBase): + + def __init__(self, f): + self.f = f + for m in self.ok_file_methods: + if not hasattr(self, m): + setattr(self, m, getattr(f, m)) + + def close(f): + self.flush() + + +TEMPLATE = """ +def %s(self, *args): + return apply(getattr(self.mod, self.name).%s, args) +""" + +class FileDelegate(FileBase): + + def __init__(self, mod, name): + self.mod = mod + self.name = name + + for m in FileBase.ok_file_methods + ('close',): + exec TEMPLATE % (m, m) + + class RHooks(ihooks.Hooks): def __init__(self, rexec, verbose=0): @@ -53,12 +91,19 @@ class RHooks(ihooks.Hooks): class RModuleLoader(ihooks.FancyModuleLoader): - pass + def load_module(self, name, stuff): + file, filename, info = stuff + m = ihooks.FancyModuleLoader.load_module(self, name, stuff) + m.__filename__ = filename + return m class RModuleImporter(ihooks.ModuleImporter): - pass + def reload(self, module, path=None): + if path is None and hasattr(module, '__filename__'): + path = [module.__filename__] + return ihooks.ModuleImporter.reload(self, module, path) class RExec(ihooks._Verbose): @@ -78,7 +123,7 @@ class RExec(ihooks._Verbose): ok_sys_names = ('ps1', 'ps2', 'copyright', 'version', 'platform', 'exit', 'maxint') - nok_builtin_names = ('open', 'reload', '__import__', 'raw_input', 'input') + nok_builtin_names = ('open', 'reload', '__import__') def __init__(self, hooks = None, verbose = 0): ihooks._Verbose.__init__(self, verbose) @@ -110,6 +155,8 @@ class RExec(ihooks._Verbose): def make_builtin(self): m = self.copy_except(__builtin__, self.nok_builtin_names) m.__import__ = self.r_import + m.reload = self.r_reload + m.open = self.r_open def make_main(self): m = self.add_module('__main__') @@ -180,6 +227,60 @@ class RExec(ihooks._Verbose): def r_import(self, mname, globals={}, locals={}, fromlist=[]): return self.importer.import_module(mname, globals, locals, fromlist) + def r_reload(self, m): + return self.importer.reload(m) + + # The s_* methods are similar but also swap std{in,out,err} + + def set_files(self): + s = self.modules['sys'] + s.stdin = FileWrapper(sys.stdin) + s.stdout = FileWrapper(sys.stdout) + s.stderr = FileWrapper(sys.stderr) + sys.stdin = FileDelegate(s, 'stdin') + sys.stdout = FileDelegate(s, 'stdout') + sys.stderr = FileDelegate(s, 'stderr') + + def save_files(self): + self.save_stdin = sys.stdin + self.save_stdout = sys.stdout + self.save_stderr = sys.stderr + + def restore_files(files): + sys.stdin = self.save_sydin + sys.stdout = self.save_stdout + sys.stderr = self.save_stderr + + def s_apply(self, func, *args, **kw): + self.save_files() + try: + self.set_files() + r = apply(func, args, kw) + finally: + self.restore_files() + + def s_exec(self, *args): + self.s_apply(self.r_exec, args) + + def s_eval(self, *args): + self.s_apply(self.r_eval, args) + + def s_execfile(self, *args): + self.s_apply(self.r_execfile, args) + + def s_import(self, *args): + self.s_apply(self.r_import, args) + + def s_reload(self, *args): + self.s_apply(self.r_reload, args) + + # Restricted open(...) + + def r_open(self, file, mode='r', buf=-1): + if mode not in ('r', 'rb'): + raise IOError, "can't open files for writing in restricted mode" + return open(file, 'r', buf) + def test(): import traceback |