forked from vstinner/pysandbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterpreter.py
128 lines (112 loc) · 3.95 KB
/
interpreter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from __future__ import with_statement
from code import InteractiveConsole
from sandbox import Sandbox, SandboxConfig
import readline
from optparse import OptionParser
from sandbox.version import VERSION
import sys
from sys import version_info
def getEncoding():
encoding = sys.stdin.encoding
if encoding:
return encoding
# sys.stdin.encoding is None if stdin is not a tty
# Emulate PYTHONIOENCODING on Python < 2.6
import os
env = os.getenv('PYTHONIOENCODING')
if env:
return env.split(':',1)[0]
# Fallback to locales
import locale
return locale.getpreferredencoding()
ENCODING = getEncoding()
class SandboxConsole(InteractiveConsole):
# Backport Python 2.6 fix for input encoding
def raw_input(self, prompt):
line = InteractiveConsole.raw_input(self, prompt)
if not isinstance(line, unicode):
line = line.decode(ENCODING)
return line
class SandboxedInterpeter:
def __init__(self):
self.sandbox_locals = None
self.config, self.options = self.parseOptions()
self.config.enable('interpreter')
if ('traceback' in self.config.features) \
and (not self.config.cpython_restricted):
self.config.allowPath(__file__)
self.stdout = sys.stdout
def parseOptions(self):
parser = OptionParser(usage="%prog [options]")
SandboxConfig.createOptparseOptions(parser,
default_timeout=None)
parser.add_option("--verbose", "-v",
help="Verbose mode",
action="store_true", default=False)
parser.add_option("--quiet", "-q",
help="Quiet mode",
action="store_true", default=False)
options, argv = parser.parse_args()
if argv:
parser.print_help()
exit(1)
if options.quiet:
options.verbose = False
config = SandboxConfig.fromOptparseOptions(options)
return config, options
def dumpConfig(self):
if self.options.verbose:
from pprint import pprint
print "Sandbox config:"
pprint(self.config.__dict__)
else:
features = ', '.join(sorted(self.config.features))
print "Enabled features: %s" % features
if self.config.cpython_restricted:
print "CPython restricted mode enabled."
if 'help' not in self.config.features:
print "(use --features=help to enable the help function)"
print
def displayhook(self, result):
if result is None:
return
self.sandbox_locals['_'] = result
text = repr(result)
if not self.options.quiet:
print(text)
else:
self.stdout.write(text)
def interact(self):
console = SandboxConsole()
self.sandbox_locals = console.locals
if not self.options.quiet:
banner = "Try to break the sandbox!"
else:
banner = ''
console.interact(banner)
def main(self):
if not self.options.quiet:
print("pysandbox %s" % VERSION)
self.dumpConfig()
if 'help' in self.config.features:
# Import pydoc here because it uses a lot of modules
# blocked by the sandbox
import pydoc
if self.config.cpython_restricted:
# Import is blocked in restricted mode, so preload modules
import codecs
import encodings
import encodings.utf_8
import encodings.utf_16_be
if version_info >= (2, 6):
import encodings.utf_32_be
if sys.stdout.encoding:
codecs.lookup(sys.stdout.encoding)
codecs.lookup(ENCODING)
sys.ps1 = '\nsandbox>>> '
sys.ps2 = '.......... '
sys.displayhook = self.displayhook
sandbox = Sandbox(self.config)
sandbox.call(self.interact)
if __name__ == "__main__":
SandboxedInterpeter().main()