Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
code.py397 linesDownload Raw Back to Lib
1"""Utilities needed to emulate Python's interactive interpreter.2 3"""4 5# Inspired by similar code by Jeff Epler and Fredrik Lundh.6 7 8import builtins9import sys10import traceback11from codeop import CommandCompiler, compile_command12 13__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact",14           "compile_command"]15 16class InteractiveInterpreter:17    """Base class for InteractiveConsole.18 19    This class deals with parsing and interpreter state (the user's20    namespace); it doesn't deal with input buffering or prompting or21    input file naming (the filename is always passed in explicitly).22 23    """24 25    def __init__(self, locals=None):26        """Constructor.27 28        The optional 'locals' argument specifies a mapping to use as the29        namespace in which code will be executed; it defaults to a newly30        created dictionary with key "__name__" set to "__console__" and31        key "__doc__" set to None.32 33        """34        if locals is None:35            locals = {"__name__": "__console__", "__doc__": None}36        self.locals = locals37        self.compile = CommandCompiler()38 39    def runsource(self, source, filename="<input>", symbol="single"):40        """Compile and run some source in the interpreter.41 42        Arguments are as for compile_command().43 44        One of several things can happen:45 46        1) The input is incorrect; compile_command() raised an47        exception (SyntaxError or OverflowError).  A syntax traceback48        will be printed by calling the showsyntaxerror() method.49 50        2) The input is incomplete, and more input is required;51        compile_command() returned None.  Nothing happens.52 53        3) The input is complete; compile_command() returned a code54        object.  The code is executed by calling self.runcode() (which55        also handles run-time exceptions, except for SystemExit).56 57        The return value is True in case 2, False in the other cases (unless58        an exception is raised).  The return value can be used to59        decide whether to use sys.ps1 or sys.ps2 to prompt the next60        line.61 62        """63        try:64            code = self.compile(source, filename, symbol)65        except (OverflowError, SyntaxError, ValueError):66            # Case 167            self.showsyntaxerror(filename, source=source)68            return False69 70        if code is None:71            # Case 272            return True73 74        # Case 375        self.runcode(code)76        return False77 78    def runcode(self, code):79        """Execute a code object.80 81        When an exception occurs, self.showtraceback() is called to82        display a traceback.  All exceptions are caught except83        SystemExit, which is reraised.84 85        A note about KeyboardInterrupt: this exception may occur86        elsewhere in this code, and may not always be caught.  The87        caller should be prepared to deal with it.88 89        """90        try:91            exec(code, self.locals)92        except SystemExit:93            raise94        except:95            self.showtraceback()96 97    def showsyntaxerror(self, filename=None, **kwargs):98        """Display the syntax error that just occurred.99 100        This doesn't display a stack trace because there isn't one.101 102        If a filename is given, it is stuffed in the exception instead103        of what was there before (because Python's parser always uses104        "<string>" when reading from a string).105 106        The output is written by self.write(), below.107 108        """109        try:110            typ, value, tb = sys.exc_info()111            if filename and issubclass(typ, SyntaxError):112                value.filename = filename113            source = kwargs.pop('source', "")114            self._showtraceback(typ, value, None, source)115        finally:116            typ = value = tb = None117 118    def showtraceback(self):119        """Display the exception that just occurred.120 121        We remove the first stack item because it is our own code.122 123        The output is written by self.write(), below.124 125        """126        try:127            typ, value, tb = sys.exc_info()128            self._showtraceback(typ, value, tb.tb_next, "")129        finally:130            typ = value = tb = None131 132    def _showtraceback(self, typ, value, tb, source):133        sys.last_type = typ134        sys.last_traceback = tb135        value = value.with_traceback(tb)136        # Set the line of text that the exception refers to137        lines = source.splitlines()138        if (source and typ is SyntaxError139                and not value.text and value.lineno is not None140                and len(lines) >= value.lineno):141            value.text = lines[value.lineno - 1]142        sys.last_exc = sys.last_value = value143        if sys.excepthook is sys.__excepthook__:144            self._excepthook(typ, value, tb)145        else:146            # If someone has set sys.excepthook, we let that take precedence147            # over self.write148            try:149                sys.excepthook(typ, value, tb)150            except SystemExit:151                raise152            except BaseException as e:153                e.__context__ = None154                e = e.with_traceback(e.__traceback__.tb_next)155                print('Error in sys.excepthook:', file=sys.stderr)156                sys.__excepthook__(type(e), e, e.__traceback__)157                print(file=sys.stderr)158                print('Original exception was:', file=sys.stderr)159                sys.__excepthook__(typ, value, tb)160 161    def _excepthook(self, typ, value, tb):162        # This method is being overwritten in163        # _pyrepl.console.InteractiveColoredConsole164        lines = traceback.format_exception(typ, value, tb)165        self.write(''.join(lines))166 167    def write(self, data):168        """Write a string.169 170        The base implementation writes to sys.stderr; a subclass may171        replace this with a different implementation.172 173        """174        sys.stderr.write(data)175 176 177class InteractiveConsole(InteractiveInterpreter):178    """Closely emulate the behavior of the interactive Python interpreter.179 180    This class builds on InteractiveInterpreter and adds prompting181    using the familiar sys.ps1 and sys.ps2, and input buffering.182 183    """184 185    def __init__(self, locals=None, filename="<console>", *, local_exit=False):186        """Constructor.187 188        The optional locals argument will be passed to the189        InteractiveInterpreter base class.190 191        The optional filename argument should specify the (file)name192        of the input stream; it will show up in tracebacks.193 194        """195        InteractiveInterpreter.__init__(self, locals)196        self.filename = filename197        self.local_exit = local_exit198        self.resetbuffer()199 200    def resetbuffer(self):201        """Reset the input buffer."""202        self.buffer = []203 204    def interact(self, banner=None, exitmsg=None):205        """Closely emulate the interactive Python console.206 207        The optional banner argument specifies the banner to print208        before the first interaction; by default it prints a banner209        similar to the one printed by the real Python interpreter,210        followed by the current class name in parentheses (so as not211        to confuse this with the real interpreter -- since it's so212        close!).213 214        The optional exitmsg argument specifies the exit message215        printed when exiting. Pass the empty string to suppress216        printing an exit message. If exitmsg is not given or None,217        a default message is printed.218 219        """220        try:221            sys.ps1222            delete_ps1_after = False223        except AttributeError:224            sys.ps1 = ">>> "225            delete_ps1_after = True226        try:227            _ps2 = sys.ps2228            delete_ps2_after = False229        except AttributeError:230            sys.ps2 = "... "231            delete_ps2_after = True232 233        cprt = 'Type "help", "copyright", "credits" or "license" for more information.'234        if banner is None:235            self.write("Python %s on %s\n%s\n(%s)\n" %236                       (sys.version, sys.platform, cprt,237                        self.__class__.__name__))238        elif banner:239            self.write("%s\n" % str(banner))240        more = 0241 242        # When the user uses exit() or quit() in their interactive shell243        # they probably just want to exit the created shell, not the whole244        # process. exit and quit in builtins closes sys.stdin which makes245        # it super difficult to restore246        #247        # When self.local_exit is True, we overwrite the builtins so248        # exit() and quit() only raises SystemExit and we can catch that249        # to only exit the interactive shell250 251        _exit = None252        _quit = None253 254        if self.local_exit:255            if hasattr(builtins, "exit"):256                _exit = builtins.exit257                builtins.exit = Quitter("exit")258 259            if hasattr(builtins, "quit"):260                _quit = builtins.quit261                builtins.quit = Quitter("quit")262 263        try:264            while True:265                try:266                    if more:267                        prompt = sys.ps2268                    else:269                        prompt = sys.ps1270                    try:271                        line = self.raw_input(prompt)272                    except EOFError:273                        self.write("\n")274                        break275                    else:276                        more = self.push(line)277                except KeyboardInterrupt:278                    self.write("\nKeyboardInterrupt\n")279                    self.resetbuffer()280                    more = 0281                except SystemExit as e:282                    if self.local_exit:283                        self.write("\n")284                        break285                    else:286                        raise e287        finally:288            # restore exit and quit in builtins if they were modified289            if _exit is not None:290                builtins.exit = _exit291 292            if _quit is not None:293                builtins.quit = _quit294 295            if delete_ps1_after:296                del sys.ps1297 298            if delete_ps2_after:299                del sys.ps2300 301            if exitmsg is None:302                self.write('now exiting %s...\n' % self.__class__.__name__)303            elif exitmsg != '':304                self.write('%s\n' % exitmsg)305 306    def push(self, line, filename=None, _symbol="single"):307        """Push a line to the interpreter.308 309        The line should not have a trailing newline; it may have310        internal newlines.  The line is appended to a buffer and the311        interpreter's runsource() method is called with the312        concatenated contents of the buffer as source.  If this313        indicates that the command was executed or invalid, the buffer314        is reset; otherwise, the command is incomplete, and the buffer315        is left as it was after the line was appended.  The return316        value is 1 if more input is required, 0 if the line was dealt317        with in some way (this is the same as runsource()).318 319        """320        self.buffer.append(line)321        source = "\n".join(self.buffer)322        if filename is None:323            filename = self.filename324        more = self.runsource(source, filename, symbol=_symbol)325        if not more:326            self.resetbuffer()327        return more328 329    def raw_input(self, prompt=""):330        """Write a prompt and read a line.331 332        The returned line does not include the trailing newline.333        When the user enters the EOF key sequence, EOFError is raised.334 335        The base implementation uses the built-in function336        input(); a subclass may replace this with a different337        implementation.338 339        """340        return input(prompt)341 342 343class Quitter:344    def __init__(self, name):345        self.name = name346        if sys.platform == "win32":347            self.eof = 'Ctrl-Z plus Return'348        else:349            self.eof = 'Ctrl-D (i.e. EOF)'350 351    def __repr__(self):352        return f'Use {self.name} or {self.eof} to exit'353 354    def __call__(self, code=None):355        raise SystemExit(code)356 357 358def interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False):359    """Closely emulate the interactive Python interpreter.360 361    This is a backwards compatible interface to the InteractiveConsole362    class.  When readfunc is not specified, it attempts to import the363    readline module to enable GNU readline if it is available.364 365    Arguments (all optional, all default to None):366 367    banner -- passed to InteractiveConsole.interact()368    readfunc -- if not None, replaces InteractiveConsole.raw_input()369    local -- passed to InteractiveInterpreter.__init__()370    exitmsg -- passed to InteractiveConsole.interact()371    local_exit -- passed to InteractiveConsole.__init__()372 373    """374    console = InteractiveConsole(local, local_exit=local_exit)375    if readfunc is not None:376        console.raw_input = readfunc377    else:378        try:379            import readline  # noqa: F401380        except ImportError:381            pass382    console.interact(banner, exitmsg)383 384 385if __name__ == "__main__":386    import argparse387 388    parser = argparse.ArgumentParser(color=True)389    parser.add_argument('-q', action='store_true',390                       help="don't print version and copyright messages")391    args = parser.parse_args()392    if args.q or sys.flags.quiet:393        banner = ''394    else:395        banner = None396    interact(banner)397 
codekingpro/portable-devtools · Team Ai