Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I not paste the output of Pythons REPL without manual-editing?

A huge amount of example Python code shows the output of the Python REPL, for example:

>>> class eg(object):
...     def __init__(self, name):
...             self.name = name
...     def hi(self):
...             print "Hi %s" % (self.name)
... 
>>> greeter = eg("Bob")
>>> greeter.hi()
Hi Bob
>>> 

Now, the obvious thing you want to do is run the above code.. so, I run "python" and paste the above text in..

>>> >>> class eg(object):
  File "<stdin>", line 1
    >>> class eg(object):
     ^
SyntaxError: invalid syntax
>>> ...     def __init__(self, name):
  File "<stdin>", line 1
    ...     def __init__(self, name):
    ^

The code is broken!?..

To get it to run, I would have to either..

  • copy-and-paste the lines one at a time, making sure I copy all the indentation correctly. If you screw it up (say, miss a leading space, you have to start all over again)
  • use a text editor to remove >>> and ..., then paste again

It's not a huge issue, but given how much example code is presented in this format, it seems strange you have to do this..

like image 816
dbr Avatar asked Dec 18 '22 08:12

dbr


2 Answers

How to run/adopt "the output of Pythons REPL"

  • Use IPython shell

    In [99]: %cpaste
    Pasting code; enter '--' alone on the line to stop.
    :>>> class eg(object):
    :...     def __init__(self, name):
    :...             self.name = name
    :...     def hi(self):
    :...             print "Hi %s" % (self.name)
    :...
    :>>> greeter = eg("Bob")
    :>>> greeter.hi()
    :--
    Hi Bob
    
  • Use a capable text editor (e.g., C-x r k kills rectangular region in Emacs)

  • Use doctest module

Copy without the shell prompt in the first place (though I don't know how to do it on Google Chrome, for example).

Why the doctest format is used

Save the following to documentation.txt:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. 

>>> class eg(object):
...     def __init__(self, name):
...             self.name = name
...     def hi(self):
...             print "Hi %s" % (self.name)
... 
>>> greeter = eg("Bob")
>>> greeter.hi()
Hi Bob
>>>

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.

Run:

$ python -c "import doctest; doctest.testfile('documentation.txt')" -v

Output:

Trying:
    class eg(object):
        def __init__(self, name):
                self.name = name
        def hi(self):
                print "Hi %s" % (self.name)
Expecting nothing
ok
Trying:
    greeter = eg("Bob")
Expecting nothing
ok
Trying:
    greeter.hi()
Expecting:
    Hi Bob
ok
1 items passed all tests:
   3 tests in doctest.txt
3 tests in 1 items.
3 passed and 0 failed.
Test passed.

If you add the following snippet at the end of your module it will test all code in its docstrings:

if __name__=="__main__":
   import doctest; doctest.testmod()

QED

like image 148
jfs Avatar answered May 14 '23 04:05

jfs


I don't know if there's a good solution out there for this. Ideally, there'd be some way to modify the behavior of the interpretter to accept copy/paste input of this sort. Here are some alternate suggestions:

Use triple quoting to save the example to a string. Then, use exec:

>>> def chomp_prompt(s): return '\n'.join(ln[4:] for ln in s.splitlines())
...
>>> dirty = """>>> class eg(object):
... ...     def __init__(self, name):
... ...             self.name = name
... ...     def hi(self):
... ...             print "Hi %s" % (self.name)
... ...
... >>> greeter = eg("Bob")
... >>> greeter.hi()
... """
>>> clean = chomp_prompt(dirty)
>>> exec clean
Hi Bob
>>>

Not only does my solution all fit on one line (so it'll be easy for you to copy/paste it in the interpreter), it works on the above example :D :

>>> s = r'''>>> def chomp_prompt(s): return '\n'.join(ln[4:] for ln in s.splitlines())
... ...
... >>> dirty = """>>> class eg(object):
... ... ...     def __init__(self, name):
... ... ...             self.name = name
... ... ...     def hi(self):
... ... ...             print "Hi %s" % (self.name)
... ... ...
... ... >>> greeter = eg("Bob")
... ... >>> greeter.hi()
... ... """
... >>> clean = chomp_prompt(dirty)
... >>> exec clean'''
>>> s2 = chomp_prompt(s)
>>> exec s2
Hi Bob

My second suggestion is to look at ipython's ability to open an editor for you and execute what you entered there after you're done editing:

http://ipython.scipy.org/doc/rel-0.9.1/html/interactive/tutorial.html#source-code-handling-tips

If you set emacs as your editor, I know it has the ability to delete a rectangle of text (you can probably guess the command: M-x delete-rectangle), which would work perfectly for getting rid of those pesky prompts. I'm sure many other editors have this as well.

like image 33
allyourcode Avatar answered May 14 '23 02:05

allyourcode