]> code.delx.au - gnu-emacs/blobdiff - lisp/org/ob-python.el
Fix typos.
[gnu-emacs] / lisp / org / ob-python.el
index c082188bea7790566b2d6ee414ae6822f9d81f6f..5234d83eceec6e4f330c459ecd32d6fb3a0ba53d 100644 (file)
@@ -1,11 +1,12 @@
 ;;; ob-python.el --- org-babel functions for python evaluation
 
-;; Copyright (C) 2009, 2010  Free Software Foundation
+;; Copyright (C) 2009-2011  Free Software Foundation
 
-;; Author: Eric Schulte, Dan Davison
+;; Author: Eric Schulte
+;;     Dan Davison
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: http://orgmode.org
-;; Version: 7.01
+;; Version: 7.7
 
 ;; This file is part of GNU Emacs.
 
 
 (declare-function org-remove-indentation "org" )
 (declare-function py-shell "ext:python-mode" (&optional argprompt))
+(declare-function py-toggle-shells "ext:python-mode" (arg))
 (declare-function run-python "ext:python" (&optional cmd noshow new))
 
+(defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("python" . "py"))
 
 (defvar org-babel-default-header-args:python '())
   "Name of command for executing python code.")
 
 (defvar org-babel-python-mode (if (featurep 'xemacs) 'python-mode 'python)
-  "Preferred python mode for use in running python interactively.")
-
-(defun org-babel-expand-body:python (body params &optional processed-params)
-  "Expand BODY according to PARAMS, return the expanded body."
-  (concat
-   (mapconcat ;; define any variables
-    (lambda (pair)
-      (format "%s=%s"
-              (car pair)
-              (org-babel-python-var-to-python (cdr pair))))
-    (nth 1 (or processed-params (org-babel-process-params params))) "\n")
-   "\n" (org-babel-trim body) "\n"))
+  "Preferred python mode for use in running python interactively.
+This will typically be either 'python or 'python-mode.")
+
+(defvar org-src-preserve-indentation)
 
 (defun org-babel-execute:python (body params)
   "Execute a block of Python code with Babel.
 This function is called by `org-babel-execute-src-block'."
-  (let* ((processed-params (org-babel-process-params params))
-         (session (org-babel-python-initiate-session (first processed-params)))
-         (result-params (nth 2 processed-params))
-         (result-type (nth 3 processed-params))
-         (full-body (org-babel-expand-body:python
-                     body params processed-params))
+  (let* ((session (org-babel-python-initiate-session
+                  (cdr (assoc :session params))))
+         (result-params (cdr (assoc :result-params params)))
+         (result-type (cdr (assoc :result-type params)))
+        (return-val (when (and (eq result-type 'value) (not session))
+                      (cdr (assoc :return params))))
+        (preamble (cdr (assoc :preamble params)))
+         (full-body
+         (org-babel-expand-body:generic
+          (concat body (if return-val (format "return %s" return-val) ""))
+          params (org-babel-variable-assignments:python params)))
          (result (org-babel-python-evaluate
-                 session full-body result-type result-params)))
-    (or (cdr (assoc :file params))
-        (org-babel-reassemble-table
-         result
-         (org-babel-pick-name (nth 4 processed-params)
-                             (cdr (assoc :colnames params)))
-         (org-babel-pick-name (nth 5 processed-params)
-                             (cdr (assoc :rownames params)))))))
+                 session full-body result-type result-params preamble)))
+    (org-babel-reassemble-table
+     result
+     (org-babel-pick-name (cdr (assoc :colname-names params))
+                         (cdr (assoc :colnames params)))
+     (org-babel-pick-name (cdr (assoc :rowname-names params))
+                         (cdr (assoc :rownames params))))))
 
 (defun org-babel-prep-session:python (session params)
-  "Prepare SESSION according to the header arguments in PARAMS."
+  "Prepare SESSION according to the header arguments in PARAMS.
+VARS contains resolved variable references"
   (let* ((session (org-babel-python-initiate-session session))
-         (vars (org-babel-ref-variables params))
-         (var-lines (mapcar ;; define any variables
-                     (lambda (pair)
-                       (format "%s=%s"
-                               (car pair)
-                               (org-babel-python-var-to-python (cdr pair))))
-                     vars)))
+        (var-lines
+         (org-babel-variable-assignments:python params)))
     (org-babel-comint-in-buffer session
       (mapc (lambda (var)
               (end-of-line 1) (insert var) (comint-send-input)
@@ -104,6 +99,15 @@ This function is called by `org-babel-execute-src-block'."
 
 ;; helper functions
 
+(defun org-babel-variable-assignments:python (params)
+  "Return list of python statements assigning the block's variables"
+  (mapcar
+   (lambda (pair)
+     (format "%s=%s"
+            (car pair)
+            (org-babel-python-var-to-python (cdr pair))))
+   (mapcar #'cdr (org-babel-get-header params :var))))
+
 (defun org-babel-python-var-to-python (var)
   "Convert an elisp value to a python variable.
 Convert an elisp value, VAR, into a string of python source code
@@ -120,21 +124,7 @@ specifying a variable of the same value."
   "Convert RESULTS into an appropriate elisp value.
 If the results look like a list or tuple, then convert them into an
 Emacs-lisp table, otherwise return the results as a string."
-  ((lambda (res)
-     (if (listp res)
-        (mapcar (lambda (el) (if (equal el 'None) 'hline el)) res)
-       res))
-   (org-babel-read
-   (if (or (string-match "^\\[.+\\]$" results)
-          (string-match "^(.+)$" results))
-       (org-babel-read
-        (concat "'"
-                (replace-regexp-in-string
-                 "\\[" "(" (replace-regexp-in-string
-                            "\\]" ")" (replace-regexp-in-string
-                                       ", " " " (replace-regexp-in-string
-                                                 "'" "\"" results t))))))
-     results))))
+  (org-babel-script-escape results))
 
 (defvar org-babel-python-buffers '((:default . nil)))
 
@@ -142,6 +132,7 @@ Emacs-lisp table, otherwise return the results as a string."
   "Return the buffer associated with SESSION."
   (cdr (assoc session org-babel-python-buffers)))
 
+(defvar py-default-interpreter)
 (defun org-babel-python-initiate-session-by-key (&optional session)
   "Initiate a python session.
 If there is not a current inferior-process-buffer in SESSION
@@ -151,14 +142,18 @@ then create.  Return the initialized session."
     (let* ((session (if session (intern session) :default))
            (python-buffer (org-babel-python-session-buffer session)))
       (cond
-       ((and (equal 'python org-babel-python-mode)
+       ((and (eq 'python org-babel-python-mode)
             (fboundp 'run-python)) ; python.el
        (run-python))
-       ((and (equal 'python-mode org-babel-python-mode)
+       ((and (eq 'python-mode org-babel-python-mode)
             (fboundp 'py-shell)) ; python-mode.el
+       ;; Make sure that py-which-bufname is initialized, as otherwise
+       ;; it will be overwritten the first time a Python buffer is
+       ;; created.
+       (py-toggle-shells py-default-interpreter)
        ;; `py-shell' creates a buffer whose name is the value of
        ;; `py-which-bufname' with '*'s at the beginning and end
-       (let* ((bufname (if python-buffer
+       (let* ((bufname (if (and python-buffer (buffer-live-p python-buffer))
                            (replace-regexp-in-string ;; zap surrounding *
                             "^\\*\\([^*]+\\)\\*$" "\\1" python-buffer)
                          (concat "Python-" (symbol-name session))))
@@ -195,73 +190,102 @@ def main():
 open('%s', 'w').write( pprint.pformat(main()) )")
 
 (defun org-babel-python-evaluate
-  (buffer body &optional result-type result-params)
-  "Pass BODY to the Python process in BUFFER.
-If RESULT-TYPE equals 'output then return a list of the outputs
-of the statements in BODY, if RESULT-TYPE equals 'value then
-return the value of the last statement in BODY, as elisp."
-  (if (not buffer)
-      ;; external process evaluation
-      (case result-type
-       (output (org-babel-eval org-babel-python-command body))
-       (value (let ((tmp-file (make-temp-file "org-babel-python-results-")))
-                (org-babel-eval org-babel-python-command
-                                (format
-                                 (if (member "pp" result-params)
-                                     org-babel-python-pp-wrapper-method
-                                   org-babel-python-wrapper-method)
-                                 (mapconcat
-                                  (lambda (line) (format "\t%s" line))
-                                  (split-string
-                                   (org-remove-indentation
-                                    (org-babel-trim body))
-                                   "[\r\n]") "\n")
-                                 tmp-file))
-                ((lambda (raw)
-                   (if (or (member "code" result-params)
-                           (member "pp" result-params))
-                       raw
-                     (org-babel-python-table-or-string raw)))
-                 (org-babel-eval-read-file tmp-file)))))
-    ;; comint session evaluation
-    (flet ((dump-last-value (tmp-file pp)
-           (mapc
-            (lambda (statement) (insert statement) (comint-send-input))
-            (if pp
-                (list
-                 "import pp"
-                 (format "open('%s', 'w').write(pprint.pformat(_))" tmp-file))
-              (list (format "open('%s', 'w').write(str(_))" tmp-file)))))
-          (input-body (body)
-           (mapc (lambda (statement) (insert statement) (comint-send-input))
-                 (split-string (org-babel-trim body) "[\r\n]+"))
-           (comint-send-input) (comint-send-input)))
-      (case result-type
-       (output
-        (mapconcat
-         #'org-babel-trim
-         (butlast
-          (org-babel-comint-with-output
-              (buffer org-babel-python-eoe-indicator t body)
-            (let ((comint-process-echoes nil))
-              (input-body body)
-              (insert org-babel-python-eoe-indicator)
-              (comint-send-input))) 2) "\n"))
-       (value
-        ((lambda (results)
-           (if (or (member "code" result-params) (member "pp" result-params))
-               results
-             (org-babel-python-table-or-string results)))
-         (let ((tmp-file (make-temp-file "org-babel-python-results-")))
-           (org-babel-comint-with-output
-               (buffer org-babel-python-eoe-indicator t body)
-             (let ((comint-process-echoes nil))
-               (input-body body)
-               (dump-last-value tmp-file (member "pp" result-params))
-               (comint-send-input) (comint-send-input)
-               (insert org-babel-python-eoe-indicator)
-               (comint-send-input)))
-           (org-babel-eval-read-file tmp-file))))))))
+  (session body &optional result-type result-params preamble)
+  "Evaluate BODY as python code."
+  (if session
+      (org-babel-python-evaluate-session
+       session body result-type result-params)
+    (org-babel-python-evaluate-external-process
+     body result-type result-params preamble)))
+
+(defun org-babel-python-evaluate-external-process
+  (body &optional result-type result-params preamble)
+  "Evaluate BODY in external python process.
+If RESULT-TYPE equals 'output then return standard output as a
+string. If RESULT-TYPE equals 'value then return the value of the
+last statement in BODY, as elisp."
+  ((lambda (raw)
+     (if (or (member "code" result-params)
+            (member "pp" result-params)
+            (and (member "output" result-params)
+                 (not (member "table" result-params))))
+        raw
+       (org-babel-python-table-or-string (org-babel-trim raw))))
+   (case result-type
+     (output (org-babel-eval org-babel-python-command
+                            (concat (if preamble (concat preamble "\n") "")
+                                    body)))
+     (value (let ((tmp-file (org-babel-temp-file "python-")))
+             (org-babel-eval
+              org-babel-python-command
+              (concat
+               (if preamble (concat preamble "\n") "")
+               (format
+                (if (member "pp" result-params)
+                    org-babel-python-pp-wrapper-method
+                  org-babel-python-wrapper-method)
+                (mapconcat
+                 (lambda (line) (format "\t%s" line))
+                 (split-string
+                  (org-remove-indentation
+                   (org-babel-trim body))
+                  "[\r\n]") "\n")
+                (org-babel-process-file-name tmp-file 'noquote))))
+             (org-babel-eval-read-file tmp-file))))))
+
+(defun org-babel-python-evaluate-session
+  (session body &optional result-type result-params)
+  "Pass BODY to the Python process in SESSION.
+If RESULT-TYPE equals 'output then return standard output as a
+string. If RESULT-TYPE equals 'value then return the value of the
+last statement in BODY, as elisp."
+  (flet ((send-wait () (comint-send-input nil t) (sleep-for 0 5))
+        (dump-last-value
+         (tmp-file pp)
+         (mapc
+          (lambda (statement) (insert statement) (send-wait))
+          (if pp
+              (list
+               "import pprint"
+               (format "open('%s', 'w').write(pprint.pformat(_))"
+                       (org-babel-process-file-name tmp-file 'noquote)))
+            (list (format "open('%s', 'w').write(str(_))"
+                          (org-babel-process-file-name tmp-file 'noquote))))))
+        (input-body (body)
+                    (mapc (lambda (line) (insert line) (send-wait))
+                          (split-string body "[\r\n]"))
+                    (send-wait)))
+    ((lambda (results)
+       (unless (string= (substring org-babel-python-eoe-indicator 1 -1) results)
+        (if (or (member "code" result-params)
+                (member "pp" result-params)
+                (and (member "output" result-params)
+                     (not (member "table" result-params))))
+            results
+          (org-babel-python-table-or-string results))))
+     (case result-type
+       (output
+       (mapconcat
+        #'org-babel-trim
+        (butlast
+         (org-babel-comint-with-output
+             (session org-babel-python-eoe-indicator t body)
+           (input-body body)
+           (send-wait) (send-wait)
+           (insert org-babel-python-eoe-indicator)
+           (send-wait))
+         2) "\n"))
+       (value
+       (let ((tmp-file (org-babel-temp-file "python-")))
+         (org-babel-comint-with-output
+             (session org-babel-python-eoe-indicator nil body)
+           (let ((comint-process-echoes nil))
+             (input-body body)
+             (dump-last-value tmp-file (member "pp" result-params))
+             (send-wait) (send-wait)
+             (insert org-babel-python-eoe-indicator)
+             (send-wait)))
+         (org-babel-eval-read-file tmp-file)))))))
 
 (defun org-babel-python-read-string (string)
   "Strip 's from around python string"
@@ -271,6 +295,6 @@ return the value of the last statement in BODY, as elisp."
 
 (provide 'ob-python)
 
-;; arch-tag: f19b6c3d-dfcb-4a1a-9ce0-45ade1ebc212
+
 
 ;;; ob-python.el ends here