Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 1 | import string |
| 2 | import sys |
| 3 | import traceback |
| 4 | |
| 5 | |
| 6 | try: |
| 7 | sys.ps1 |
| 8 | except AttributeError: |
| 9 | sys.ps1 = ">>> " |
| 10 | try: |
| 11 | sys.ps2 |
| 12 | except AttributeError: |
| 13 | sys.ps2 = "... " |
| 14 | |
| 15 | |
| 16 | def print_exc(limit=None, file=None): |
| 17 | if not file: |
| 18 | file = sys.stderr |
| 19 | # we're going to skip the outermost traceback object, we don't |
| 20 | # want people to see the line which excecuted their code. |
| 21 | tb = sys.exc_traceback |
| 22 | if tb: |
| 23 | tb = tb.tb_next |
| 24 | try: |
| 25 | sys.last_type = sys.exc_type |
| 26 | sys.last_value = sys.exc_value |
| 27 | sys.last_traceback = tb |
| 28 | traceback.print_exception(sys.last_type, sys.last_value, |
| 29 | sys.last_traceback, limit, file) |
| 30 | except: |
| 31 | print '--- hola! ---' |
| 32 | traceback.print_exception(sys.exc_type, sys.exc_value, |
| 33 | sys.exc_traceback, limit, file) |
| 34 | |
| 35 | |
| 36 | class PyInteractive: |
| 37 | |
| 38 | def __init__(self): |
| 39 | self._pybuf = "" |
| 40 | |
| 41 | def executeline(self, stuff, out = None, env = None): |
| 42 | if env is None: |
| 43 | import __main__ |
| 44 | env = __main__.__dict__ |
| 45 | if out: |
| 46 | saveerr, saveout = sys.stderr, sys.stdout |
| 47 | sys.stderr = sys.stdout = out |
| 48 | try: |
| 49 | if self._pybuf: |
| 50 | self._pybuf = self._pybuf + '\n' + stuff |
| 51 | else: |
| 52 | self._pybuf = stuff |
| 53 | |
| 54 | # Compile three times: as is, with \n, and with \n\n appended. |
| 55 | # If it compiles as is, it's complete. If it compiles with |
| 56 | # one \n appended, we expect more. If it doesn't compile |
| 57 | # either way, we compare the error we get when compiling with |
| 58 | # \n or \n\n appended. If the errors are the same, the code |
| 59 | # is broken. But if the errors are different, we expect more. |
| 60 | # Not intuitive; not even guaranteed to hold in future |
| 61 | # releases; but this matches the compiler's behavior in Python |
| 62 | # 1.4 and 1.5. |
| 63 | err = err1 = err2 = None |
| 64 | code = code1 = code2 = None |
| 65 | |
| 66 | # quickly get out of here when the line is 'empty' or is a comment |
| 67 | stripped = string.strip(self._pybuf) |
| 68 | if not stripped or stripped[0] == '#': |
| 69 | self._pybuf = '' |
| 70 | sys.stdout.write(sys.ps1) |
| 71 | sys.stdout.flush() |
| 72 | return |
| 73 | |
| 74 | try: |
| 75 | code = compile(self._pybuf, "<input>", "single") |
| 76 | except SyntaxError, err: |
| 77 | pass |
| 78 | except: |
| 79 | # OverflowError. More? |
| 80 | print_exc() |
| 81 | self._pybuf = "" |
| 82 | sys.stdout.write(sys.ps1) |
| 83 | sys.stdout.flush() |
| 84 | return |
| 85 | |
| 86 | try: |
| 87 | code1 = compile(self._pybuf + "\n", "<input>", "single") |
| 88 | except SyntaxError, err1: |
| 89 | pass |
| 90 | |
| 91 | try: |
| 92 | code2 = compile(self._pybuf + "\n\n", "<input>", "single") |
| 93 | except SyntaxError, err2: |
| 94 | pass |
| 95 | |
| 96 | if code: |
| 97 | try: |
| 98 | exec code in env |
| 99 | except: |
| 100 | print_exc() |
| 101 | self._pybuf = "" |
| 102 | elif code1: |
| 103 | pass |
| 104 | elif err1 == err2 or (not stuff and self._pybuf): |
| 105 | print_exc() |
| 106 | self._pybuf = "" |
| 107 | if self._pybuf: |
| 108 | sys.stdout.write(sys.ps2) |
| 109 | sys.stdout.flush() |
| 110 | else: |
| 111 | sys.stdout.write(sys.ps1) |
| 112 | sys.stdout.flush() |
| 113 | finally: |
| 114 | if out: |
| 115 | sys.stderr, sys.stdout = saveerr, saveout |