aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorAugusto Stoffel2021-09-03 14:26:51 +0200
committerLars Ingebrigtsen2021-09-03 14:26:51 +0200
commite32c7d2a8d1635af5234a8ceabbdbe911abc9a7b (patch)
tree01f706c3efd2e4051b53416343a107dec9a7a4d9 /lisp/progmodes/python.el
parent34550b44924cac96ece0ae0cd215dea433dd863a (diff)
downloademacs-e32c7d2a8d1635af5234a8ceabbdbe911abc9a7b.tar.gz
emacs-e32c7d2a8d1635af5234a8ceabbdbe911abc9a7b.zip
Change Python eval to send directly instead of using temporary files
* lisp/progmodes/python.el (python-shell-eval-setup-code): New const for setting up eval (bug#49822). (python-shell--encode-string): New function. (python-shell-send-string): Use it to send commands directly instead of writing to a temporary file. (python-shell-send-string-no-output): Adjust sending. (python-shell-send-file): Ditto.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el64
1 files changed, 50 insertions, 14 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index d5209d8d2f1..306cc3a5428 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3081,6 +3081,45 @@ there for compatibility with CEDET.")
3081 (delete-trailing-whitespace)) 3081 (delete-trailing-whitespace))
3082 temp-file-name)) 3082 temp-file-name))
3083 3083
3084(defconst python-shell-eval-setup-code
3085 "\
3086def __PYTHON_EL_eval(source, filename):
3087 import ast, sys
3088 if sys.version_info[0] == 2:
3089 from __builtin__ import compile, eval, globals
3090 else:
3091 from builtins import compile, eval, globals
3092 sys.stdout.write('\\n')
3093 try:
3094 p, e = ast.parse(source, filename), None
3095 except SyntaxError:
3096 t, v, tb = sys.exc_info()
3097 sys.excepthook(t, v, tb.tb_next)
3098 return
3099 if p.body and isinstance(p.body[-1], ast.Expr):
3100 e = p.body.pop()
3101 try:
3102 g = globals()
3103 exec(compile(p, filename, 'exec'), g, g)
3104 if e:
3105 return eval(compile(ast.Expression(e.value), filename, 'eval'), g, g)
3106 except Exception:
3107 t, v, tb = sys.exc_info()
3108 sys.excepthook(t, v, tb.tb_next)"
3109 "Code used to evaluate statements in inferior Python processes.")
3110
3111(defalias 'python-shell--encode-string
3112 (let ((fun (if (and (fboundp 'json-serialize)
3113 (>= emacs-major-version 28))
3114 'json-serialize
3115 (require 'json)
3116 'json-encode-string)))
3117 (lambda (text)
3118 (if (stringp text)
3119 (funcall fun text)
3120 (signal 'wrong-type-argument (list 'stringp text)))))
3121 "Encode TEXT as a valid Python string.")
3122
3084(defun python-shell-send-string (string &optional process msg) 3123(defun python-shell-send-string (string &optional process msg)
3085 "Send STRING to inferior Python PROCESS. 3124 "Send STRING to inferior Python PROCESS.
3086When optional argument MSG is non-nil, forces display of a 3125When optional argument MSG is non-nil, forces display of a
@@ -3088,16 +3127,12 @@ user-friendly message if there's no process running; defaults to
3088t when called interactively." 3127t when called interactively."
3089 (interactive 3128 (interactive
3090 (list (read-string "Python command: ") nil t)) 3129 (list (read-string "Python command: ") nil t))
3091 (let ((process (or process (python-shell-get-process-or-error msg)))) 3130 (comint-send-string
3092 (if (string-match ".\n+." string) ;Multiline. 3131 (or process (python-shell-get-process-or-error msg))
3093 (let* ((temp-file-name (with-current-buffer (process-buffer process) 3132 (format "exec(%s);__PYTHON_EL_eval(%s, %s)\n"
3094 (python-shell--save-temp-file string))) 3133 (python-shell--encode-string python-shell-eval-setup-code)
3095 (file-name (or (buffer-file-name) temp-file-name))) 3134 (python-shell--encode-string string)
3096 (python-shell-send-file file-name process temp-file-name t)) 3135 (python-shell--encode-string (or (buffer-file-name) "<string>")))))
3097 (comint-send-string process string)
3098 (when (or (not (string-match "\n\\'" string))
3099 (string-match "\n[ \t].*\n?\\'" string))
3100 (comint-send-string process "\n")))))
3101 3136
3102(defvar python-shell-output-filter-in-progress nil) 3137(defvar python-shell-output-filter-in-progress nil)
3103(defvar python-shell-output-filter-buffer nil) 3138(defvar python-shell-output-filter-buffer nil)
@@ -3139,7 +3174,8 @@ Return the output."
3139 (inhibit-quit t)) 3174 (inhibit-quit t))
3140 (or 3175 (or
3141 (with-local-quit 3176 (with-local-quit
3142 (python-shell-send-string string process) 3177 (comint-send-string
3178 process (format "exec(%s)\n" (python-shell--encode-string string)))
3143 (while python-shell-output-filter-in-progress 3179 (while python-shell-output-filter-in-progress
3144 ;; `python-shell-output-filter' takes care of setting 3180 ;; `python-shell-output-filter' takes care of setting
3145 ;; `python-shell-output-filter-in-progress' to NIL after it 3181 ;; `python-shell-output-filter-in-progress' to NIL after it
@@ -3362,7 +3398,8 @@ t when called interactively."
3362 (temp-file-name (when temp-file-name 3398 (temp-file-name (when temp-file-name
3363 (file-local-name (expand-file-name 3399 (file-local-name (expand-file-name
3364 temp-file-name))))) 3400 temp-file-name)))))
3365 (python-shell-send-string 3401 (comint-send-string
3402 process
3366 (format 3403 (format
3367 (concat 3404 (concat
3368 "import codecs, os;" 3405 "import codecs, os;"
@@ -3372,8 +3409,7 @@ t when called interactively."
3372 (when (and delete temp-file-name) 3409 (when (and delete temp-file-name)
3373 (format "os.remove('''%s''');" temp-file-name)) 3410 (format "os.remove('''%s''');" temp-file-name))
3374 "exec(compile(__code, '''%s''', 'exec'));") 3411 "exec(compile(__code, '''%s''', 'exec'));")
3375 (or temp-file-name file-name) encoding encoding file-name) 3412 (or temp-file-name file-name) encoding encoding file-name))))
3376 process)))
3377 3413
3378(defun python-shell-switch-to-shell (&optional msg) 3414(defun python-shell-switch-to-shell (&optional msg)
3379 "Switch to inferior Python process buffer. 3415 "Switch to inferior Python process buffer.