emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Extraneous output from Python code blocks using :session option
@ 2015-03-11  3:38 Richard Stanton
  2015-03-11 18:29 ` Kyle Meyer
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Stanton @ 2015-03-11  3:38 UTC (permalink / raw)
  To: emacs-orgmode

I'm trying to use the :session option so I can import modules, etc., just once at the beginning of my document, like with am IPython notebook. Unfortunately, the output from these code blocks contains some extraneous characters. For example:

#+BEGIN_SRC python :session :results output
a = 2
b = 3
c = 4
print 'a=      ', a
print 'b =     ', b
print 'a + b = ', a+b
#+END_SRC

#+RESULTS:
: 
: >>> >>> a=       2
: b =      3
: a + b =  5

How can I stop the production of all those ">" signs (sometimes they're dots), which don't appear if I run the same code block without the :session option?

Thanks.

Richard Stanton

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-11  3:38 Extraneous output from Python code blocks using :session option Richard Stanton
@ 2015-03-11 18:29 ` Kyle Meyer
  2015-03-11 18:54   ` Richard Stanton
  2015-03-12 15:17   ` John Kitchin
  0 siblings, 2 replies; 12+ messages in thread
From: Kyle Meyer @ 2015-03-11 18:29 UTC (permalink / raw)
  To: Richard Stanton; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1125 bytes --]

Richard Stanton <stanton@haas.berkeley.edu> wrote:
> I'm trying to use the :session option so I can import modules, etc.,
> just once at the beginning of my document, like with am IPython
> notebook. Unfortunately, the output from these code blocks contains
> some extraneous characters. For example:
>
> #+BEGIN_SRC python :session :results output
> a = 2
> b = 3
> c = 4
> print 'a=      ', a
> print 'b =     ', b
> print 'a + b = ', a+b
> #+END_SRC
>
> #+RESULTS:
> :
> : >>> >>> a=       2
> : b =      3
> : a + b =  5

I also see this behavior.  I asked the list some time ago [1], but I
didn't follow up beyond the initial email.

> How can I stop the production of all those ">" signs (sometimes
> they're dots), which don't appear if I run the same code block without
> the :session option?

I've attached a patch that seems to fix the example you gave and the
cases from my earlier email.  I don't know enough about babel's
internals to know if it is a good way to fix it, but at least it might
serve as a quick fix for you until there is a better solution.

[1] http://thread.gmane.org/gmane.emacs.orgmode/79014


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ob-python.el-Strip-leading-session-characters.patch --]
[-- Type: text/x-diff, Size: 2137 bytes --]

From cfa2783e03152871c0d703a6f79e96254dbe6c44 Mon Sep 17 00:00:00 2001
From: Kyle Meyer <kyle@kyleam.com>
Date: Wed, 11 Mar 2015 14:17:09 -0400
Subject: [PATCH] ob-python.el: Strip leading session characters

* lisp/ob-python.el (org-babel-python-evaluate-session): Strip leading
  "..." and ">>>" from session output.
(org-babel-python-strip-session-chars): New function.
---
 lisp/ob-python.el | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index dd3cc66..0267f22 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -306,16 +306,17 @@ (defun org-babel-python-evaluate-session
          (results
           (case result-type
             (output
-             (mapconcat
-              #'org-babel-trim
-              (butlast
-               (org-babel-comint-with-output
-                   (session org-babel-python-eoe-indicator t body)
-                 (funcall input-body body)
-                 (funcall send-wait) (funcall send-wait)
-                 (insert org-babel-python-eoe-indicator)
-                 (funcall send-wait))
-               2) "\n"))
+	     (org-babel-python-strip-session-chars
+	      (mapconcat
+	       #'org-babel-chomp
+	       (butlast
+		(org-babel-comint-with-output
+		    (session org-babel-python-eoe-indicator t body)
+		  (funcall input-body body)
+		  (funcall send-wait) (funcall send-wait)
+		  (insert org-babel-python-eoe-indicator)
+		  (funcall send-wait))
+		2) "\n")))
             (value
              (let ((tmp-file (org-babel-temp-file "python-")))
                (org-babel-comint-with-output
@@ -339,6 +340,15 @@ (defun org-babel-python-read-string (string)
       (match-string 1 string)
     string))
 
+(defun org-babel-python-strip-session-chars (string)
+  "Remove leading >>> and ... from Python session output."
+  (with-temp-buffer
+    (insert string)
+    (goto-char (point-min))
+    (when (looking-at "\\s-*\\(\\(>>> \\)*\\(\\.\\.\\. \\)*\\)")
+      (delete-region (match-beginning 1) (match-end 1)))
+    (buffer-string)))
+
 (provide 'ob-python)
 
 
-- 
2.3.2


[-- Attachment #3: Type: text/plain, Size: 9 bytes --]


--
Kyle

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-11 18:29 ` Kyle Meyer
@ 2015-03-11 18:54   ` Richard Stanton
  2015-03-12 15:17   ` John Kitchin
  1 sibling, 0 replies; 12+ messages in thread
From: Richard Stanton @ 2015-03-11 18:54 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode

> On Mar 11, 2015, at 11:29 AM, Kyle Meyer <kyle@kyleam.com> wrote:
> 
> Richard Stanton <stanton@haas.berkeley.edu> wrote:
>> I'm trying to use the :session option so I can import modules, etc.,
>> just once at the beginning of my document, like with am IPython
>> notebook. Unfortunately, the output from these code blocks contains
>> some extraneous characters. For example:
>> 
>> #+BEGIN_SRC python :session :results output
>> a = 2
>> b = 3
>> c = 4
>> print 'a=      ', a
>> print 'b =     ', b
>> print 'a + b = ', a+b
>> #+END_SRC
>> 
>> #+RESULTS:
>> :
>> : >>> >>> a=       2
>> : b =      3
>> : a + b =  5
> 
> I also see this behavior.  I asked the list some time ago [1], but I
> didn't follow up beyond the initial email.
> 
>> How can I stop the production of all those ">" signs (sometimes
>> they're dots), which don't appear if I run the same code block without
>> the :session option?
> 
> I've attached a patch that seems to fix the example you gave and the
> cases from my earlier email.  I don't know enough about babel's
> internals to know if it is a good way to fix it, but at least it might
> serve as a quick fix for you until there is a better solution.
> 
> [1] http://thread.gmane.org/gmane.emacs.orgmode/79014
> 
> From cfa2783e03152871c0d703a6f79e96254dbe6c44 Mon Sep 17 00:00:00 2001
> From: Kyle Meyer <kyle@kyleam.com>
> Date: Wed, 11 Mar 2015 14:17:09 -0400
> Subject: [PATCH] ob-python.el: Strip leading session characters
> 
> * lisp/ob-python.el (org-babel-python-evaluate-session): Strip leading
>  "..." and ">>>" from session output.
> (org-babel-python-strip-session-chars): New function.
> ---
> lisp/ob-python.el | 30 ++++++++++++++++++++----------
> 1 file changed, 20 insertions(+), 10 deletions(-)
> 
> diff --git a/lisp/ob-python.el b/lisp/ob-python.el
> index dd3cc66..0267f22 100644
> --- a/lisp/ob-python.el
> +++ b/lisp/ob-python.el
> @@ -306,16 +306,17 @@ (defun org-babel-python-evaluate-session
>          (results
>           (case result-type
>             (output
> -             (mapconcat
> -              #'org-babel-trim
> -              (butlast
> -               (org-babel-comint-with-output
> -                   (session org-babel-python-eoe-indicator t body)
> -                 (funcall input-body body)
> -                 (funcall send-wait) (funcall send-wait)
> -                 (insert org-babel-python-eoe-indicator)
> -                 (funcall send-wait))
> -               2) "\n"))
> +	     (org-babel-python-strip-session-chars
> +	      (mapconcat
> +	       #'org-babel-chomp
> +	       (butlast
> +		(org-babel-comint-with-output
> +		    (session org-babel-python-eoe-indicator t body)
> +		  (funcall input-body body)
> +		  (funcall send-wait) (funcall send-wait)
> +		  (insert org-babel-python-eoe-indicator)
> +		  (funcall send-wait))
> +		2) "\n")))
>             (value
>              (let ((tmp-file (org-babel-temp-file "python-")))
>                (org-babel-comint-with-output
> @@ -339,6 +340,15 @@ (defun org-babel-python-read-string (string)
>       (match-string 1 string)
>     string))
> 
> +(defun org-babel-python-strip-session-chars (string)
> +  "Remove leading >>> and ... from Python session output."
> +  (with-temp-buffer
> +    (insert string)
> +    (goto-char (point-min))
> +    (when (looking-at "\\s-*\\(\\(>>> \\)*\\(\\.\\.\\. \\)*\\)")
> +      (delete-region (match-beginning 1) (match-end 1)))
> +    (buffer-string)))
> +
> (provide 'ob-python)
> 
> 
> -- 
> 2.3.2
> 
> 
> —
> Kyle

Many thanks, Kyle. It would be great if this could be fixed in the main code, but I’ll try your patch today.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-11 18:29 ` Kyle Meyer
  2015-03-11 18:54   ` Richard Stanton
@ 2015-03-12 15:17   ` John Kitchin
  2015-03-12 15:34     ` Richard Stanton
  2015-03-12 21:21     ` Kyle Meyer
  1 sibling, 2 replies; 12+ messages in thread
From: John Kitchin @ 2015-03-12 15:17 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: Richard Stanton, emacs-orgmode

Nice. I hope this makes it into org-mode one day.

In the mean time, I crafted an approach with another hook function that
is described here:

http://kitchingroup.cheme.cmu.edu/blog/2015/03/12/Making-org-mode-Python-sessions-look-better/

This can be done in an init file.

Kyle Meyer writes:

> Richard Stanton <stanton@haas.berkeley.edu> wrote:
>> I'm trying to use the :session option so I can import modules, etc.,
>> just once at the beginning of my document, like with am IPython
>> notebook. Unfortunately, the output from these code blocks contains
>> some extraneous characters. For example:
>>
>> #+BEGIN_SRC python :session :results output
>> a = 2
>> b = 3
>> c = 4
>> print 'a=      ', a
>> print 'b =     ', b
>> print 'a + b = ', a+b
>> #+END_SRC
>>
>> #+RESULTS:
>> :
>> : >>> >>> a=       2
>> : b =      3
>> : a + b =  5
>
> I also see this behavior.  I asked the list some time ago [1], but I
> didn't follow up beyond the initial email.
>
>> How can I stop the production of all those ">" signs (sometimes
>> they're dots), which don't appear if I run the same code block without
>> the :session option?
>
> I've attached a patch that seems to fix the example you gave and the
> cases from my earlier email.  I don't know enough about babel's
> internals to know if it is a good way to fix it, but at least it might
> serve as a quick fix for you until there is a better solution.
>
> [1] http://thread.gmane.org/gmane.emacs.orgmode/79014

--
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-12 15:17   ` John Kitchin
@ 2015-03-12 15:34     ` Richard Stanton
  2015-03-12 21:23       ` Kyle Meyer
  2015-03-12 21:21     ` Kyle Meyer
  1 sibling, 1 reply; 12+ messages in thread
From: Richard Stanton @ 2015-03-12 15:34 UTC (permalink / raw)
  To: John Kitchin; +Cc: Kyle Meyer, emacs-orgmode

This looks great. While we're patching this code, why does having blank lines inside function definitions cause such problems in :session mode? It would be nice if you could just type any valid Python code and have it execute (like you can in an IPython notebook cell)


> On Mar 12, 2015, at 8:17 AM, John Kitchin <jkitchin@andrew.cmu.edu> wrote:
> 
> Nice. I hope this makes it into org-mode one day.
> 
> In the mean time, I crafted an approach with another hook function that
> is described here:
> 
> http://kitchingroup.cheme.cmu.edu/blog/2015/03/12/Making-org-mode-Python-sessions-look-better/
> 
> This can be done in an init file.
> 
> Kyle Meyer writes:
> 
>> Richard Stanton <stanton@haas.berkeley.edu> wrote:
>>> I'm trying to use the :session option so I can import modules, etc.,
>>> just once at the beginning of my document, like with am IPython
>>> notebook. Unfortunately, the output from these code blocks contains
>>> some extraneous characters. For example:
>>> 
>>> #+BEGIN_SRC python :session :results output
>>> a = 2
>>> b = 3
>>> c = 4
>>> print 'a=      ', a
>>> print 'b =     ', b
>>> print 'a + b = ', a+b
>>> #+END_SRC
>>> 
>>> #+RESULTS:
>>> :
>>> : >>> >>> a=       2
>>> : b =      3
>>> : a + b =  5
>> 
>> I also see this behavior.  I asked the list some time ago [1], but I
>> didn't follow up beyond the initial email.
>> 
>>> How can I stop the production of all those ">" signs (sometimes
>>> they're dots), which don't appear if I run the same code block without
>>> the :session option?
>> 
>> I've attached a patch that seems to fix the example you gave and the
>> cases from my earlier email.  I don't know enough about babel's
>> internals to know if it is a good way to fix it, but at least it might
>> serve as a quick fix for you until there is a better solution.
>> 
>> [1] http://thread.gmane.org/gmane.emacs.orgmode/79014
> 
> --
> Professor John Kitchin
> Doherty Hall A207F
> Department of Chemical Engineering
> Carnegie Mellon University
> Pittsburgh, PA 15213
> 412-268-7803
> @johnkitchin
> http://kitchingroup.cheme.cmu.edu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-12 15:17   ` John Kitchin
  2015-03-12 15:34     ` Richard Stanton
@ 2015-03-12 21:21     ` Kyle Meyer
  1 sibling, 0 replies; 12+ messages in thread
From: Kyle Meyer @ 2015-03-12 21:21 UTC (permalink / raw)
  To: John Kitchin; +Cc: Richard Stanton, emacs-orgmode

John Kitchin <jkitchin@andrew.cmu.edu> wrote:
> Nice. I hope this makes it into org-mode one day.
>
> In the mean time, I crafted an approach with another hook function that
> is described here:
>
> http://kitchingroup.cheme.cmu.edu/blog/2015/03/12/Making-org-mode-Python-sessions-look-better/

Good idea.  Thanks for the information.

--
Kyle

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-12 15:34     ` Richard Stanton
@ 2015-03-12 21:23       ` Kyle Meyer
  2015-03-13  6:58         ` Kyle Meyer
  0 siblings, 1 reply; 12+ messages in thread
From: Kyle Meyer @ 2015-03-12 21:23 UTC (permalink / raw)
  To: Richard Stanton; +Cc: emacs-orgmode, John Kitchin

Richard Stanton <stanton@haas.berkeley.edu> wrote:
> This looks great. While we're patching this code, why does having
> blank lines inside function definitions cause such problems in
> :session mode?

I think this is because the lines are being sent one by one, so sending
the blank line causes an issue, like typing enter with the cursor at _:

    >>> def abc():
    >>> _

    ...
      File "<stdin>", line 2

        ^
    IndentationError: expected an indented block
    >>>

I'll take a look at fixing this.  python.el in Emacs 24 seems to send
functions with blank lines over fine, so perhaps I can use it as an
example.

--
Kyle

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-12 21:23       ` Kyle Meyer
@ 2015-03-13  6:58         ` Kyle Meyer
  2015-03-13  8:21           ` Nicolas Goaziou
  0 siblings, 1 reply; 12+ messages in thread
From: Kyle Meyer @ 2015-03-13  6:58 UTC (permalink / raw)
  To: Richard Stanton; +Cc: emacs-orgmode, John Kitchin

[-- Attachment #1: Type: text/plain, Size: 1049 bytes --]

Kyle Meyer <kyle@kyleam.com> wrote:
> Richard Stanton <stanton@haas.berkeley.edu> wrote:
>> This looks great. While we're patching this code, why does having
>> blank lines inside function definitions cause such problems in
>> :session mode?
>
> I think this is because the lines are being sent one by one, so sending
> the blank line causes an issue, like typing enter with the cursor at _:
>
>     >>> def abc():
>     >>> _
>
>     ...
>       File "<stdin>", line 2
>
>         ^
>     IndentationError: expected an indented block
>     >>>
>
> I'll take a look at fixing this.  python.el in Emacs 24 seems to send
> functions with blank lines over fine, so perhaps I can use it as an
> example.

I've attached two patches.  The first one is a proposed way to deal with
the indentation issues in sessions.  It is very similar to what
python.el does for multiline input (use a temporary file and then
execute that from the shell).  The second is an update of my previous
patch to remove shell prompt characters that are leaking into the
output.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ob-python.el-Allow-indented-code-in-sessions.patch --]
[-- Type: text/x-diff, Size: 2950 bytes --]

From 28f271314f7bff7c54696defe8e451da69cd2d6c Mon Sep 17 00:00:00 2001
From: Kyle Meyer <kyle@kyleam.com>
Date: Fri, 13 Mar 2015 02:45:04 -0400
Subject: [PATCH 1/2] ob-python.el: Allow indented code in sessions

* lisp/ob-python.el (org-babel-python-evaluate-session): Recognize
indented code in session and treat it differently to avoid syntax
errors.

For session blocks with results set to 'output', go through an
intermediate file when there is indented code to prevent
indentation-related errors when sending code to the Python shell.  For
session blocks with results set to 'value', issue an user-error.
These (usually) would have resulted in a syntax error in the shell
anyway, and the '_' variable can't be used to get the last value here
(as it is for non-indented code) because it isn't set when executing
the code through a file.
---
 lisp/ob-python.el | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index dd3cc66..8c51679 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -238,6 +238,14 @@ (defconst org-babel-python-pp-wrapper-method
 
 open('%s', 'w').write( pprint.pformat(main()) )")
 
+(defconst org-babel-python-indented-lines-session-method
+  (concat "fname= '%s'; fh = open(fname); "
+	  "exec(compile(fh.read(), fname, 'exec')); "
+	  "fh.close()")
+  "Single line to execute indented Python code in session.
+%s will be formatted with the file name of the file containing
+ the code.")
+
 (defun org-babel-python-evaluate
   (session body &optional result-type result-params preamble)
   "Evaluate BODY as Python code."
@@ -303,6 +311,13 @@ (defun org-babel-python-evaluate-session
 		       (mapc (lambda (line) (insert line) (funcall send-wait))
 			     (split-string body "[\r\n]"))
 		       (funcall send-wait)))
+	 (indented-p (org-babel-python--indented-p body))
+	 (body (if indented-p
+		   (let ((tmp-file (org-babel-temp-file "python-")))
+		     (with-temp-file tmp-file (insert body))
+		     (format org-babel-python-indented-lines-session-method
+			     tmp-file))
+		 body))
          (results
           (case result-type
             (output
@@ -317,6 +332,8 @@ (defun org-babel-python-evaluate-session
                  (funcall send-wait))
                2) "\n"))
             (value
+	     (when indented-p
+	       (user-error "Value output limited to unindented lines with session"))
              (let ((tmp-file (org-babel-temp-file "python-")))
                (org-babel-comint-with-output
                    (session org-babel-python-eoe-indicator nil body)
@@ -339,6 +356,13 @@ (defun org-babel-python-read-string (string)
       (match-string 1 string)
     string))
 
+(defun org-babel-python--indented-p (input)
+  "Return true if any line in INPUT is indented."
+  (with-temp-buffer
+    (insert input)
+    (goto-char (point-min))
+    (re-search-forward "^\\s-" nil t)))
+
 (provide 'ob-python)
 
 
-- 
2.3.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-ob-python.el-Strip-leading-session-characters.patch --]
[-- Type: text/x-diff, Size: 2314 bytes --]

From 3d433fac1162f1544fbcfc7e4a8675a258764f34 Mon Sep 17 00:00:00 2001
From: Kyle Meyer <kyle@kyleam.com>
Date: Fri, 13 Mar 2015 02:46:38 -0400
Subject: [PATCH 2/2] ob-python.el: Strip leading session characters

* lisp/ob-python.el (org-babel-python-evaluate-session): Strip extra leading
  "..." and ">>>" from session output.
---
 lisp/ob-python.el | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index 8c51679..170b6cd 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -321,16 +321,17 @@ (defun org-babel-python-evaluate-session
          (results
           (case result-type
             (output
-             (mapconcat
-              #'org-babel-trim
-              (butlast
-               (org-babel-comint-with-output
-                   (session org-babel-python-eoe-indicator t body)
-                 (funcall input-body body)
-                 (funcall send-wait) (funcall send-wait)
-                 (insert org-babel-python-eoe-indicator)
-                 (funcall send-wait))
-               2) "\n"))
+	     (org-babel-python--strip-session-chars
+	      (mapconcat
+	       #'org-babel-chomp
+	       (butlast
+		(org-babel-comint-with-output
+		    (session org-babel-python-eoe-indicator t body)
+		  (funcall input-body body)
+		  (funcall send-wait) (funcall send-wait)
+		  (insert org-babel-python-eoe-indicator)
+		  (funcall send-wait))
+		2) "\n")))
             (value
 	     (when indented-p
 	       (user-error "Value output limited to unindented lines with session"))
@@ -363,6 +364,19 @@ (defun org-babel-python--indented-p (input)
     (goto-char (point-min))
     (re-search-forward "^\\s-" nil t)))
 
+(defun org-babel-python--strip-session-chars (string)
+  "Remove leading '>>>' and '...' from Python session output.
+`org-babel-comint-with-output' splits by
+`comint-prompt-regexp' (which includes '>>>' and '...'), but, in
+some situations, these still make it through at the start of the
+output string."
+  (with-temp-buffer
+    (insert string)
+    (goto-char (point-min))
+    (when (looking-at "\\s-*\n\\(\\(>>> \\)\\|\\(\\.\\.\\. \\)\\)*")
+      (delete-region (match-beginning 0) (match-end 0)))
+    (buffer-string)))
+
 (provide 'ob-python)
 
 
-- 
2.3.1


[-- Attachment #4: Type: text/plain, Size: 9 bytes --]


--
Kyle

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-13  6:58         ` Kyle Meyer
@ 2015-03-13  8:21           ` Nicolas Goaziou
  2015-03-13 14:40             ` Kyle Meyer
  0 siblings, 1 reply; 12+ messages in thread
From: Nicolas Goaziou @ 2015-03-13  8:21 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: Richard Stanton, emacs-orgmode, John Kitchin

Hello,

Kyle Meyer <kyle@kyleam.com> writes:

> I've attached two patches.  The first one is a proposed way to deal with
> the indentation issues in sessions.  It is very similar to what
> python.el does for multiline input (use a temporary file and then
> execute that from the shell).  The second is an update of my previous
> patch to remove shell prompt characters that are leaking into the
> output.

Thank you.

I'll just comment about code, not functionality.

> +(defconst org-babel-python-indented-lines-session-method
> +  (concat "fname= '%s'; fh = open(fname); "
> +	  "exec(compile(fh.read(), fname, 'exec')); "
> +	  "fh.close()")
> +  "Single line to execute indented Python code in session.
> +%s will be formatted with the file name of the file containing
> + the code.")
  ^^^
spurious space

> +(defun org-babel-python--indented-p (input)
> +  "Return true if any line in INPUT is indented."

Non-nil if ...

> +  (with-temp-buffer
> +    (insert input)
> +    (goto-char (point-min))
> +    (re-search-forward "^\\s-" nil t)))

aka

  (org-string-match-p "^[ \t]" input)

> +(defun org-babel-python--strip-session-chars (string)
> +  "Remove leading '>>>' and '...' from Python session output.
> +`org-babel-comint-with-output' splits by
> +`comint-prompt-regexp' (which includes '>>>' and '...'), but, in
> +some situations, these still make it through at the start of the
> +output string."

Argument STRING is not explained in the docstring.

> +  (with-temp-buffer
> +    (insert string)
> +    (goto-char (point-min))
> +    (when (looking-at "\\s-*\n\\(\\(>>> \\)\\|\\(\\.\\.\\. \\)\\)*")
> +      (delete-region (match-beginning 0) (match-end 0)))
> +    (buffer-string)))

aka

  (replace-regexp-in-string "\\`\\s-*\n\\(>>> \\|\\.\\.\\. \\)*" "" string)


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-13  8:21           ` Nicolas Goaziou
@ 2015-03-13 14:40             ` Kyle Meyer
  2015-03-14  8:26               ` Nicolas Goaziou
  0 siblings, 1 reply; 12+ messages in thread
From: Kyle Meyer @ 2015-03-13 14:40 UTC (permalink / raw)
  To: Richard Stanton; +Cc: emacs-orgmode, John Kitchin

[-- Attachment #1: Type: text/plain, Size: 593 bytes --]

Nicolas Goaziou <mail@nicolasgoaziou.fr> wrote:
> Hello,
>
> Kyle Meyer <kyle@kyleam.com> writes:
>
>> I've attached two patches.  The first one is a proposed way to deal with
>> the indentation issues in sessions.  It is very similar to what
>> python.el does for multiline input (use a temporary file and then
>> execute that from the shell).  The second is an update of my previous
>> patch to remove shell prompt characters that are leaking into the
>> output.
>
> Thank you.
>
> I'll just comment about code, not functionality.

Thanks for your comments.  I've attached updated patches.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ob-python.el-Allow-indented-code-in-sessions.patch --]
[-- Type: text/x-diff, Size: 2593 bytes --]

From 41aae465038fd789fe92611ecf1fae7e9d08ab5b Mon Sep 17 00:00:00 2001
From: Kyle Meyer <kyle@kyleam.com>
Date: Fri, 13 Mar 2015 02:45:04 -0400
Subject: [PATCH 1/2] ob-python.el: Allow indented code in sessions

* lisp/ob-python.el (org-babel-python-evaluate-session): Recognize
indented code in session and treat it differently to avoid syntax
errors.

For session blocks with results set to 'output', go through an
intermediate file when there is indented code to prevent
indentation-related errors when sending code to the Python shell.  For
session blocks with results set to 'value', issue an user-error.
These (usually) would have resulted in a syntax error in the shell
anyway, and the '_' variable can't be used to get the last value here
(as it is for non-indented code) because it isn't set when executing
the code through a file.
---
 lisp/ob-python.el | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index dd3cc66..0dc74ca 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -238,6 +238,14 @@ (defconst org-babel-python-pp-wrapper-method
 
 open('%s', 'w').write( pprint.pformat(main()) )")
 
+(defconst org-babel-python-indented-lines-session-method
+  (concat "fname= '%s'; fh = open(fname); "
+	  "exec(compile(fh.read(), fname, 'exec')); "
+	  "fh.close()")
+  "Single line to execute indented Python code in session.
+%s will be formatted with the file name of the file containing
+the code.")
+
 (defun org-babel-python-evaluate
   (session body &optional result-type result-params preamble)
   "Evaluate BODY as Python code."
@@ -303,6 +311,13 @@ (defun org-babel-python-evaluate-session
 		       (mapc (lambda (line) (insert line) (funcall send-wait))
 			     (split-string body "[\r\n]"))
 		       (funcall send-wait)))
+	 (indented-p (org-string-match-p "^[ \t]" body))
+	 (body (if indented-p
+		   (let ((tmp-file (org-babel-temp-file "python-")))
+		     (with-temp-file tmp-file (insert body))
+		     (format org-babel-python-indented-lines-session-method
+			     tmp-file))
+		 body))
          (results
           (case result-type
             (output
@@ -317,6 +332,8 @@ (defun org-babel-python-evaluate-session
                  (funcall send-wait))
                2) "\n"))
             (value
+	     (when indented-p
+	       (user-error "Value output limited to unindented lines with session"))
              (let ((tmp-file (org-babel-temp-file "python-")))
                (org-babel-comint-with-output
                    (session org-babel-python-eoe-indicator nil body)
-- 
2.3.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-ob-python.el-Strip-leading-session-characters.patch --]
[-- Type: text/x-diff, Size: 2161 bytes --]

From 28b6a003e4ae1dbb1474350203444e76df9e8572 Mon Sep 17 00:00:00 2001
From: Kyle Meyer <kyle@kyleam.com>
Date: Fri, 13 Mar 2015 02:46:38 -0400
Subject: [PATCH 2/2] ob-python.el: Strip leading session characters

* lisp/ob-python.el (org-babel-python-evaluate-session): Strip extra leading
  "..." and ">>>" from session output.
---
 lisp/ob-python.el | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index 0dc74ca..e976d9c 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -321,16 +321,17 @@ (defun org-babel-python-evaluate-session
          (results
           (case result-type
             (output
-             (mapconcat
-              #'org-babel-trim
-              (butlast
-               (org-babel-comint-with-output
-                   (session org-babel-python-eoe-indicator t body)
-                 (funcall input-body body)
-                 (funcall send-wait) (funcall send-wait)
-                 (insert org-babel-python-eoe-indicator)
-                 (funcall send-wait))
-               2) "\n"))
+	     (org-babel-python--strip-session-chars
+	      (mapconcat
+	       #'org-babel-chomp
+	       (butlast
+		(org-babel-comint-with-output
+		    (session org-babel-python-eoe-indicator t body)
+		  (funcall input-body body)
+		  (funcall send-wait) (funcall send-wait)
+		  (insert org-babel-python-eoe-indicator)
+		  (funcall send-wait))
+		2) "\n")))
             (value
 	     (when indented-p
 	       (user-error "Value output limited to unindented lines with session"))
@@ -356,6 +357,15 @@ (defun org-babel-python-read-string (string)
       (match-string 1 string)
     string))
 
+(defun org-babel-python--strip-session-chars (string)
+  "Remove leading '>>>' and '...' from STRING.
+`org-babel-comint-with-output' splits the Python session output
+by `comint-prompt-regexp' (which includes '>>>' and '...'), but,
+in some situations, these still make it through at the start of
+the output string."
+  (replace-regexp-in-string "\\`\\s-*\n\\(>>> \\|\\.\\.\\. \\)*" ""
+			    string))
+
 (provide 'ob-python)
 
 
-- 
2.3.1


[-- Attachment #4: Type: text/plain, Size: 9 bytes --]


--
Kyle

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-13 14:40             ` Kyle Meyer
@ 2015-03-14  8:26               ` Nicolas Goaziou
  2015-03-16  0:40                 ` Kyle Meyer
  0 siblings, 1 reply; 12+ messages in thread
From: Nicolas Goaziou @ 2015-03-14  8:26 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: Richard Stanton, emacs-orgmode, John Kitchin

Kyle Meyer <kyle@kyleam.com> writes:

> Thanks for your comments.  I've attached updated patches.

Thanks.

> Subject: [PATCH 1/2] ob-python.el: Allow indented code in sessions
>
> * lisp/ob-python.el (org-babel-python-evaluate-session): Recognize
> indented code in session and treat it differently to avoid syntax
> errors.

You also need to list new functions and variables in commit message,
e.g.,

  (org-babel-python-indented-lines-session-method): New variable.

> * lisp/ob-python.el (org-babel-python-evaluate-session): Strip extra leading
>   "..." and ">>>" from session output.

Ditto.

  (org-babel-python--strip-session-chars): New function.

> +(defun org-babel-python--strip-session-chars (string)
> +  "Remove leading '>>>' and '...' from STRING.
> +`org-babel-comint-with-output' splits the Python session output
> +by `comint-prompt-regexp' (which includes '>>>' and '...'), but,
> +in some situations, these still make it through at the start of
> +the output string."

Wouldn't it be better to find the situations above at the source? If may
be due to some indentation problem at the beginning of the string, in
which case an `org-trim' within `org-babel-comint-with-output' could
solve it.

WDYT?


Regards,

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Extraneous output from Python code blocks using :session option
  2015-03-14  8:26               ` Nicolas Goaziou
@ 2015-03-16  0:40                 ` Kyle Meyer
  0 siblings, 0 replies; 12+ messages in thread
From: Kyle Meyer @ 2015-03-16  0:40 UTC (permalink / raw)
  To: Richard Stanton; +Cc: emacs-orgmode, John Kitchin

Nicolas Goaziou <mail@nicolasgoaziou.fr> wrote:
[...]
> You also need to list new functions and variables in commit message,
> e.g.,

Thanks.  I'll update the commit messages.

> Wouldn't it be better to find the situations above at the source? If may
> be due to some indentation problem at the beginning of the string, in
> which case an `org-trim' within `org-babel-comint-with-output' could
> solve it.

I agree, but I haven't figured out a good way to do this.  As far as I
can tell, it seems like the input sent in the right format.  Instead, it
is empty prompt markers that are causing the issue (see examples at end
for details).

I think there are three separate problems with Python session output
right now.

1. The empty prompt markers from multi-line code mess up the output
   processing and leak into the final output.

   The current patch fixes this in the final combined output, but I've
   realized it doesn't cover all the cases.  (I initially thought the
   markers only leaked into the start of the output, but they can be in
   the middle as well.)

   Plus, as you mention, it seems like it'd be better to fix this more
   upstream.  Since the input seems to be sent in correctly, I think
   this leaves org-babel-comint-with-output.  Specifically, output lines
   that consist of just a prompt (like '>>> ' or '... ') could be
   filtered out before the output lines are joined and returned.
   comint-prompt-regexp could be used for this check.  One problem with
   this is that I don't know if this will have unwanted effects on the
   output for other languages that use org-babel-comint-with-output.

2. org-babel-python-evaluate-session will eat whitespace at the
   beginning of output.

   The leading spaces below would be lost in the results.

   #+begin_src python :session :results output
     print('   <-- leading spaces')
   #+end_src

   Changing org-babel-trim to org-babel-chomp in
   org-babel-python-evaluate-session fixes this.

3. Valid code that has indentation and spaces cannot be sent.

   I think this is just a limitation of the shell, since blank lines are
   used to signal the end of blocks.  One of the patches I sent deals
   with this like python.el does (by using an intermediate file).

   One issue with that patch is whether it should check for blank
   lines *and* indentation, because right now it only checks for
   indentation, meaning that some code is unnecessarily sent through an
   intermediate file.

Below are two examples that explain #1 in more detail.

* Single line

#+begin_src python :session :results output
  3
#+end_src

org-babel-python-evaluate-session splits the input by newlines,
resulting in 3 (no newline) being inserted.  It then sends this input,
followed by a few more empty inputs (not needed here, but required to
finish the block if the statement had indentation), and then inserts and
sends the babel eoe indicator.

This ends up in the Python shell as

    >>> 3
    3
    >>>
    >>>
    >>>
    >>> 'org_babel_python_eoe'
    'org_babel_python_eoe'
    >>>

org-babel-comint-with-output receives then a series of text output,

    "", "3\n>>> ", "", ">>> ", "", ">>> ", "", ">>> ", "",
    "'org_babel_python_eoe'\n>>> "

which it concatenates to

    3
    >>> >>> >>> >>> 'org_babel_python_eoe'
    >>>

It then splits this by comint-prompt-regexp, which includes '>>>'
at the start of a line, resulting in

    ("3\n" ">>> >>> >>> 'org_babel_python_eoe'\n" "")

org-babel-python-evaluate-session receives this, removes the last two
elements, and trims the first, giving the correct output:

#+RESULTS:
: 3


* Multiple lines, no indentation

Here is the same example, but with some problematic lines added to the
beginning.

#+begin_src python :session :results output
  x = 3
  y = 4
  x + y
#+end_src

org-babel-python-evaluate-session splits the input by newlines and sends
x = 3, then x = 4, and then 3, as well as the empty lines and eoe
signal.

This gets ends up in the Python shell as

    x = 3
    >>> y = 4
    >>> x + y
    7
    >>> 
    >>> 
    >>> 
    >>> 'org_babel_python_eoe'
    'org_babel_python_eoe'
    >>> 

org-babel-comint-with-output receives the a series of text output,

    "", ">>> ",  <- From 'x = 3'
    "", ">>> ",  <- From 'y = 4'
    "", "7\n>>> ", "", ">>> ", "", ">>> ", "", ">>> ", ""
    "'org_babel_python_eoe'\n>>> "

which it concatenates to

    >>> >>> 7
    >>> >>> >>> >>> 'org_babel_python_eoe'
    >>>

It then splits this by comint-prompt-regexp, which includes '>>>'
at the start of a line, resulting in

    ("" ">>> 7\n" ">>> >>> >>> 'org_babel_python_eoe'\n" "")

org-babel-python-evaluate-session receives this, removes the last two
elements, and trims the others.  Unlike the output above, this has an
empty line at the beginning due to the additional ">>> " that resulted
from "x = 3", as well as ">>> " before 7 due to the additional ">>> "
that resulted from "y = 4".

#+RESULTS:
: 
: >>> 7

--
Kyle

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-03-16  0:40 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-11  3:38 Extraneous output from Python code blocks using :session option Richard Stanton
2015-03-11 18:29 ` Kyle Meyer
2015-03-11 18:54   ` Richard Stanton
2015-03-12 15:17   ` John Kitchin
2015-03-12 15:34     ` Richard Stanton
2015-03-12 21:23       ` Kyle Meyer
2015-03-13  6:58         ` Kyle Meyer
2015-03-13  8:21           ` Nicolas Goaziou
2015-03-13 14:40             ` Kyle Meyer
2015-03-14  8:26               ` Nicolas Goaziou
2015-03-16  0:40                 ` Kyle Meyer
2015-03-12 21:21     ` Kyle Meyer

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).