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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
|
from pypy.interpreter import main, error
import sys
import code
import time
class Completer:
""" Stolen mostly from CPython's rlcompleter.py """
def __init__(self, space, w_globals):
self.space = space
self.w_globals = w_globals
def complete(self, text, state):
if state == 0:
if "." in text:
self.matches = self.attr_matches(text)
else:
self.matches = self.global_matches(text)
try:
return self.matches[state]
except IndexError:
return None
def global_matches(self, text):
import keyword
w_res = self.space.call_method(self.w_globals, "keys")
namespace_keys = self.space.unwrap(w_res)
w_res = self.space.call_method(self.space.builtin.getdict(self.space),
"keys")
builtin_keys = self.space.unwrap(w_res)
matches = []
n = len(text)
for l in [namespace_keys, builtin_keys, keyword.kwlist]:
for word in l:
if word[:n] == text and word != "__builtins__":
matches.append(word)
return matches
def attr_matches(self, text):
import re
m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
if not m:
return
expr, attr = m.group(1, 3)
s = self.space
w_obj = s.eval(expr, self.w_globals, self.w_globals)
words = self.get_words(w_obj)
w_clz = s.getattr(w_obj, s.wrap("__class__"))
words += self.get_class_members(w_clz)
matches = []
n = len(attr)
for word in words:
if word[:n] == attr and word != "__builtins__":
matches.append("%s.%s" % (expr, word))
return matches
def get_words(self, w_clz):
s = self.space
w_dir_func = s.builtin.get("dir")
w_res = s.call_function(w_dir_func, w_clz)
return s.unwrap(w_res)
def get_class_members(self, w_clz):
s = self.space
words = self.get_words(w_clz)
try:
w_bases = s.getattr(w_clz, s.wrap("__bases__"))
bases_w = s.fixedview(w_bases)
except error.OperationError:
return words
for w_clz in bases_w:
words += self.get_class_members(w_clz)
return words
class PyPyConsole(code.InteractiveConsole):
def __init__(self, objspace, verbose=0, completer=False):
code.InteractiveConsole.__init__(self)
self.space = objspace
self.verbose = verbose
space = self.space
self.console_compiler_flags = 0
mainmodule = main.ensure__main__(space)
self.w_globals = mainmodule.w_dict
space.setitem(self.w_globals, space.newtext('__builtins__'), space.builtin)
if completer:
self.enable_command_line_completer()
# forbidden:
#space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals)
space.setitem(self.w_globals, space.newtext('__pytrace__'),space.newint(0))
self.tracelevel = 0
self.console_locals = {}
def enable_command_line_completer(self):
try:
import readline
# Keep here to save windoze tears
readline.set_completer(Completer(self.space, self.w_globals).complete)
readline.parse_and_bind("tab: complete")
readline.set_history_length(25000)
try:
readline.read_history_file()
except IOError:
pass # guess it doesn't exit
import atexit
atexit.register(readline.write_history_file)
except:
pass
def interact(self, banner=None):
#banner = "Python %s in pypy\n%s / %s" % (
# sys.version, self.__class__.__name__,
# self.space.__class__.__name__)
major, minor, micro, tag, rev = self.space.unwrap(self.space.sys.get('pypy_version_info'))
elapsed = time.time() - self.space._starttime
version = "%d.%d.%d" % (major, minor, micro)
if tag != "final":
version += "-%s%d" %(tag, rev)
banner = "PyPy %s in %r on top of Python %s (startuptime: %.2f secs)" % (
version, self.space, sys.version.split()[0], elapsed)
code.InteractiveConsole.interact(self, banner)
def raw_input(self, prompt=""):
# add a character to the PyPy prompt so that you know where you
# are when you debug it with "python -i py.py"
try:
return code.InteractiveConsole.raw_input(self, prompt[0] + prompt)
except KeyboardInterrupt:
# fires into an interpreter-level console
print
banner = ("Python %s on %s\n" % (sys.version, sys.platform) +
"*** Entering interpreter-level console ***")
local = self.console_locals
# don't copy attributes that look like names that came
# from self.w_globals (itself the main offender) as they
# would then get copied back into the applevel namespace.
local.update(dict([(k,v) for (k, v) in self.__dict__.iteritems()
if not k.startswith('w_')]))
del local['locals']
for w_name in self.space.unpackiterable(self.w_globals):
local['w_' + self.space.text_w(w_name)] = (
self.space.getitem(self.w_globals, w_name))
code.interact(banner=banner, local=local)
# copy back 'w_' names
for name in local:
if name.startswith('w_'):
self.space.setitem(self.w_globals,
self.space.newtext(name[2:]),
local[name])
print '*** Leaving interpreter-level console ***'
raise
def runcode(self, code):
raise NotImplementedError
def runsource(self, source, ignored_filename="<input>", symbol="single"):
# the following hacked file name is recognized specially by error.py
compiler = self.space.getexecutioncontext().compiler
# CPython 2.6 turns console input into unicode
if isinstance(source, unicode):
source = source.encode(sys.stdin.encoding)
hacked_filename = '<inline>\n' + source
def doit():
# compile the provided input
code = compiler.compile_command(source, hacked_filename, symbol,
self.console_compiler_flags)
if code is None:
raise IncompleteInput
self.console_compiler_flags |= compiler.getcodeflags(code)
# execute it
self.settrace()
try:
code.exec_code(self.space, self.w_globals, self.w_globals)
finally:
self.unsettrace()
self.checktrace()
# run doit() in an exception-catching box
try:
main.run_toplevel(self.space, doit, verbose=self.verbose)
except IncompleteInput:
return 1
else:
return 0
def settrace(self):
if self.tracelevel:
ec = self.space.getexecutioncontext()
if not hasattr(self, '_orig_bytecode_only_trace'):
self._orig_bytecode_only_trace = ec.bytecode_only_trace
ec.bytecode_only_trace = self._do_bytecode_only_trace
def unsettrace(self):
if self.tracelevel:
ec = self.space.getexecutioncontext()
ec.bytecode_only_trace = self._orig_bytecode_only_trace
def _do_bytecode_only_trace(self, frame):
from pypy.tool.pydis import Bytecode, HAVE_ARGUMENT
if frame.hide():
return
self.unsettrace()
next_instr = frame.last_instr
opcode = ord(frame.pycode.co_code[next_instr])
oparg = 0
if opcode >= HAVE_ARGUMENT:
lo = ord(frame.pycode.co_code[next_instr+1])
hi = ord(frame.pycode.co_code[next_instr+2])
oparg = (hi * 256) | lo
class fake:
code = frame.pycode
bytecode = Bytecode(fake, next_instr, oparg, 0)
print '\t%-19s %s' % (str(frame.pycode.co_name) + ':',
bytecode.repr_with_space(self.space))
self.settrace()
def checktrace(self):
s = self.space
# Did we modify __pytrace__
tracelevel = s.int_w(s.getitem(self.w_globals,
s.wrap("__pytrace__")))
if self.tracelevel > 0 and tracelevel == 0:
self.unsettrace()
print "Tracing disabled"
if self.tracelevel == 0 and tracelevel > 0:
self.unsettrace()
print "Tracing enabled"
self.tracelevel = tracelevel
class IncompleteInput(Exception):
pass
|