Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm Python uses to decide between >>> and ... prompt in interactive console?

I'm implementing a custom (Iron)Python console.

I need to display a >>> prompt in general, but when a statement is incomplete, I need to change the prompt to ... and gather more lines before executing them.

How do I know if a line entered by a user is complete or if I need to read more lines?

A simple way seems to be checking if : is present. But I'm not sure if I'm not missing other cases where : is not present.

I looked into the IronPython source code to figure how it does this, but there are many steps involved and my simple reproduction failed to completely work.

like image 426
Meh Avatar asked Sep 10 '26 19:09

Meh


2 Answers

It's impractical to try to guess from just looking at the code string for colons and brackets. You would end up needing to implement half the Python parser to get that right.

The standard library code module reproduces the behaviour of the interactive Python interpreter, and I believe it is this module that IronPython uses to implement its console. (The CPython one isn't implemented in Python itself.)

The line-continuation logic you're interested in comes from the codeop.compile_command function.

It's a bit of a hack. Essentially it tries to compile() the given code using the obscure PyCF_DONT_IMPLY_DEDENT flag, which means it doesn't assume that any open indents are closed automatically at the end of the block. It then tries to compile it again with newlines added (causing explicit DEDENTs). If the second works but the first doesn't, you've got a potential continuation, more can be typed into the block.

like image 90
bobince Avatar answered Sep 13 '26 06:09

bobince


There are a few different ways I can think of to get the ... prompt.

  • Starting (or continuing) a block
    • def foo():
  • Unclosed parenthesis, brace, square bracket (and watch out for nesting)
    • x = (
    • x = {
    • x = [
  • Unclosed triple quoted string
    • x = '''
  • Backslash at end of line:
    • x = \
like image 35
Mark Byers Avatar answered Sep 13 '26 05:09

Mark Byers



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!