PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/interpreter/interactive.py

https://bitbucket.org/yrttyr/pypy
Python | 229 lines | 227 code | 2 blank | 0 comment | 0 complexity | 0efa6b0e011224c87b9d2c82928f47d0 MD5 | raw file
  1. from pypy.interpreter import error
  2. from pypy.interpreter import baseobjspace, module, main
  3. import sys
  4. import code
  5. import time
  6. class Completer:
  7. """ Stolen mostly from CPython's rlcompleter.py """
  8. def __init__(self, space, w_globals):
  9. self.space = space
  10. self.w_globals = w_globals
  11. def complete(self, text, state):
  12. if state == 0:
  13. if "." in text:
  14. self.matches = self.attr_matches(text)
  15. else:
  16. self.matches = self.global_matches(text)
  17. try:
  18. return self.matches[state]
  19. except IndexError:
  20. return None
  21. def global_matches(self, text):
  22. import keyword
  23. w_res = self.space.call_method(self.w_globals, "keys")
  24. namespace_keys = self.space.unwrap(w_res)
  25. w_res = self.space.call_method(self.space.builtin.getdict(self.space),
  26. "keys")
  27. builtin_keys = self.space.unwrap(w_res)
  28. matches = []
  29. n = len(text)
  30. for l in [namespace_keys, builtin_keys, keyword.kwlist]:
  31. for word in l:
  32. if word[:n] == text and word != "__builtins__":
  33. matches.append(word)
  34. return matches
  35. def attr_matches(self, text):
  36. import re
  37. m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
  38. if not m:
  39. return
  40. expr, attr = m.group(1, 3)
  41. s = self.space
  42. w_obj = s.eval(expr, self.w_globals, self.w_globals)
  43. words = self.get_words(w_obj)
  44. w_clz = s.getattr(w_obj, s.wrap("__class__"))
  45. words += self.get_class_members(w_clz)
  46. matches = []
  47. n = len(attr)
  48. for word in words:
  49. if word[:n] == attr and word != "__builtins__":
  50. matches.append("%s.%s" % (expr, word))
  51. return matches
  52. def get_words(self, w_clz):
  53. s = self.space
  54. w_dir_func = s.builtin.get("dir")
  55. w_res = s.call_function(w_dir_func, w_clz)
  56. return s.unwrap(w_res)
  57. def get_class_members(self, w_clz):
  58. s = self.space
  59. words = self.get_words(w_clz)
  60. try:
  61. w_bases = s.getattr(w_clz, s.wrap("__bases__"))
  62. bases_w = s.fixedview(w_bases)
  63. except error.OperationError:
  64. return words
  65. for w_clz in bases_w:
  66. words += self.get_class_members(w_clz)
  67. return words
  68. class PyPyConsole(code.InteractiveConsole):
  69. def __init__(self, objspace, verbose=0, completer=False):
  70. code.InteractiveConsole.__init__(self)
  71. self.space = objspace
  72. self.verbose = verbose
  73. space = self.space
  74. self.console_compiler_flags = 0
  75. mainmodule = main.ensure__main__(space)
  76. self.w_globals = mainmodule.w_dict
  77. space.setitem(self.w_globals, space.wrap('__builtins__'), space.builtin)
  78. if completer:
  79. self.enable_command_line_completer()
  80. # forbidden:
  81. #space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals)
  82. space.setitem(self.w_globals, space.wrap('__pytrace__'),space.wrap(0))
  83. self.tracelevel = 0
  84. self.console_locals = {}
  85. def enable_command_line_completer(self):
  86. try:
  87. import readline
  88. # Keep here to save windoze tears
  89. readline.set_completer(Completer(self.space, self.w_globals).complete)
  90. readline.parse_and_bind("tab: complete")
  91. readline.set_history_length(25000)
  92. try:
  93. readline.read_history_file()
  94. except IOError:
  95. pass # guess it doesn't exit
  96. import atexit
  97. atexit.register(readline.write_history_file)
  98. except:
  99. pass
  100. def interact(self, banner=None):
  101. #banner = "Python %s in pypy\n%s / %s" % (
  102. # sys.version, self.__class__.__name__,
  103. # self.space.__class__.__name__)
  104. w_sys = self.space.sys
  105. major, minor, micro, tag, rev = self.space.unwrap(self.space.sys.get('pypy_version_info'))
  106. elapsed = time.time() - self.space._starttime
  107. version = "%d.%d.%d" % (major, minor, micro)
  108. if tag != "final":
  109. version += "-%s%d" %(tag, rev)
  110. banner = "PyPy %s in %r on top of Python %s (startuptime: %.2f secs)" % (
  111. version, self.space, sys.version.split()[0], elapsed)
  112. code.InteractiveConsole.interact(self, banner)
  113. def raw_input(self, prompt=""):
  114. # add a character to the PyPy prompt so that you know where you
  115. # are when you debug it with "python -i py.py"
  116. try:
  117. return code.InteractiveConsole.raw_input(self, prompt[0] + prompt)
  118. except KeyboardInterrupt:
  119. # fires into an interpreter-level console
  120. print
  121. banner = ("Python %s on %s\n" % (sys.version, sys.platform) +
  122. "*** Entering interpreter-level console ***")
  123. local = self.console_locals
  124. # don't copy attributes that look like names that came
  125. # from self.w_globals (itself the main offender) as they
  126. # would then get copied back into the applevel namespace.
  127. local.update(dict([(k,v) for (k, v) in self.__dict__.iteritems()
  128. if not k.startswith('w_')]))
  129. del local['locals']
  130. for w_name in self.space.unpackiterable(self.w_globals):
  131. local['w_' + self.space.str_w(w_name)] = (
  132. self.space.getitem(self.w_globals, w_name))
  133. code.interact(banner=banner, local=local)
  134. # copy back 'w_' names
  135. for name in local:
  136. if name.startswith('w_'):
  137. self.space.setitem(self.w_globals,
  138. self.space.wrap(name[2:]),
  139. local[name])
  140. print '*** Leaving interpreter-level console ***'
  141. raise
  142. def runcode(self, code):
  143. raise NotImplementedError
  144. def runsource(self, source, ignored_filename="<input>", symbol="single"):
  145. # the following hacked file name is recognized specially by error.py
  146. hacked_filename = '<inline>\n' + source
  147. compiler = self.space.getexecutioncontext().compiler
  148. # CPython 2.6 turns console input into unicode
  149. if isinstance(source, unicode):
  150. source = source.encode(sys.stdin.encoding)
  151. def doit():
  152. # compile the provided input
  153. code = compiler.compile_command(source, hacked_filename, symbol,
  154. self.console_compiler_flags)
  155. if code is None:
  156. raise IncompleteInput
  157. self.console_compiler_flags |= compiler.getcodeflags(code)
  158. # execute it
  159. self.settrace()
  160. try:
  161. code.exec_code(self.space, self.w_globals, self.w_globals)
  162. finally:
  163. if self.tracelevel:
  164. self.space.unsettrace()
  165. self.checktrace()
  166. # run doit() in an exception-catching box
  167. try:
  168. main.run_toplevel(self.space, doit, verbose=self.verbose)
  169. except IncompleteInput:
  170. return 1
  171. else:
  172. return 0
  173. def settrace(self):
  174. if self.tracelevel:
  175. self.space.settrace()
  176. def checktrace(self):
  177. s = self.space
  178. # Did we modify __pytrace__
  179. tracelevel = s.int_w(s.getitem(self.w_globals,
  180. s.wrap("__pytrace__")))
  181. if self.tracelevel > 0 and tracelevel == 0:
  182. s.reset_trace()
  183. print "Tracing disabled"
  184. if self.tracelevel == 0 and tracelevel > 0:
  185. self.space.unsettrace()
  186. print "Tracing enabled"
  187. self.tracelevel = tracelevel
  188. class IncompleteInput(Exception):
  189. pass