diff options
| author | Augusto Stoffel | 2021-09-09 15:48:37 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2021-09-09 15:48:37 +0200 |
| commit | e27385ec372b36822958ebed6792ca806b1a0c3d (patch) | |
| tree | 3e9cbf40e4bbc1df424f5d7dabe95e58db8f80e8 /lisp/progmodes/python.el | |
| parent | 2be75990a7ae611e8596a91b5e124dc421ec93b4 (diff) | |
| download | emacs-e27385ec372b36822958ebed6792ca806b1a0c3d.tar.gz emacs-e27385ec372b36822958ebed6792ca806b1a0c3d.zip | |
Better treatment of line length limits for the Python inferior
* lisp/comint.el (comint-max-line-length): New constant reflecting a
safe maximum line size that can be sent to an inferior process.
* lisp/progmodes/python.el
(python-shell-comint-watch-for-first-prompt-output-filter): Send setup
code to the inferior process only once and at this stage.
(python-shell-eval-setup-code, python-shell-eval-file-setup-code):
Move, unchanged, to an earlier point to avoid byte-compiler warnings.
(python-shell-send-string-no-output): Revert changes of e32c7d2a8d
(python-shell-send-string): Use 'comint-max-line-length' to decide
when to resort to temp files.
(python-shell-send-string, python-shell-send-file): Don't send setup
code each time (bug#49822).
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 98 |
1 files changed, 51 insertions, 47 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index db7008df244..8f7bb7a8b60 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -2811,6 +2811,44 @@ eventually provide a shell." | |||
| 2811 | :type 'hook | 2811 | :type 'hook |
| 2812 | :group 'python) | 2812 | :group 'python) |
| 2813 | 2813 | ||
| 2814 | (defconst python-shell-eval-setup-code | ||
| 2815 | "\ | ||
| 2816 | def __PYTHON_EL_eval(source, filename): | ||
| 2817 | import ast, sys | ||
| 2818 | if sys.version_info[0] == 2: | ||
| 2819 | from __builtin__ import compile, eval, globals | ||
| 2820 | else: | ||
| 2821 | from builtins import compile, eval, globals | ||
| 2822 | sys.stdout.write('\\n') | ||
| 2823 | try: | ||
| 2824 | p, e = ast.parse(source, filename), None | ||
| 2825 | except SyntaxError: | ||
| 2826 | t, v, tb = sys.exc_info() | ||
| 2827 | sys.excepthook(t, v, tb.tb_next) | ||
| 2828 | return | ||
| 2829 | if p.body and isinstance(p.body[-1], ast.Expr): | ||
| 2830 | e = p.body.pop() | ||
| 2831 | try: | ||
| 2832 | g = globals() | ||
| 2833 | exec(compile(p, filename, 'exec'), g, g) | ||
| 2834 | if e: | ||
| 2835 | return eval(compile(ast.Expression(e.value), filename, 'eval'), g, g) | ||
| 2836 | except Exception: | ||
| 2837 | t, v, tb = sys.exc_info() | ||
| 2838 | sys.excepthook(t, v, tb.tb_next)" | ||
| 2839 | "Code used to evaluate statements in inferior Python processes.") | ||
| 2840 | |||
| 2841 | (defconst python-shell-eval-file-setup-code | ||
| 2842 | "\ | ||
| 2843 | def __PYTHON_EL_eval_file(filename, tempname, encoding, delete): | ||
| 2844 | import codecs, os | ||
| 2845 | with codecs.open(tempname or filename, encoding=encoding) as file: | ||
| 2846 | source = file.read().encode(encoding) | ||
| 2847 | if delete and tempname: | ||
| 2848 | os.remove(tempname) | ||
| 2849 | return __PYTHON_EL_eval(source, filename)" | ||
| 2850 | "Code used to evaluate files in inferior Python processes.") | ||
| 2851 | |||
| 2814 | (defun python-shell-comint-watch-for-first-prompt-output-filter (output) | 2852 | (defun python-shell-comint-watch-for-first-prompt-output-filter (output) |
| 2815 | "Run `python-shell-first-prompt-hook' when first prompt is found in OUTPUT." | 2853 | "Run `python-shell-first-prompt-hook' when first prompt is found in OUTPUT." |
| 2816 | (when (not python-shell--first-prompt-received) | 2854 | (when (not python-shell--first-prompt-received) |
| @@ -2826,6 +2864,15 @@ eventually provide a shell." | |||
| 2826 | (setq python-shell--first-prompt-received-output-buffer nil) | 2864 | (setq python-shell--first-prompt-received-output-buffer nil) |
| 2827 | (setq-local python-shell--first-prompt-received t) | 2865 | (setq-local python-shell--first-prompt-received t) |
| 2828 | (setq python-shell--first-prompt-received-output-buffer nil) | 2866 | (setq python-shell--first-prompt-received-output-buffer nil) |
| 2867 | (cl-letf (((symbol-function 'python-shell-send-string) | ||
| 2868 | (lambda (string process) | ||
| 2869 | (comint-send-string | ||
| 2870 | process | ||
| 2871 | (format "exec(%s)\n" (python-shell--encode-string string)))))) | ||
| 2872 | ;; Bootstrap: the normal definition of `python-shell-send-string' | ||
| 2873 | ;; depends on the Python code sent here. | ||
| 2874 | (python-shell-send-string-no-output python-shell-eval-setup-code) | ||
| 2875 | (python-shell-send-string-no-output python-shell-eval-file-setup-code)) | ||
| 2829 | (with-current-buffer (current-buffer) | 2876 | (with-current-buffer (current-buffer) |
| 2830 | (let ((inhibit-quit nil)) | 2877 | (let ((inhibit-quit nil)) |
| 2831 | (run-hooks 'python-shell-first-prompt-hook)))))) | 2878 | (run-hooks 'python-shell-first-prompt-hook)))))) |
| @@ -3081,33 +3128,6 @@ there for compatibility with CEDET.") | |||
| 3081 | (delete-trailing-whitespace)) | 3128 | (delete-trailing-whitespace)) |
| 3082 | temp-file-name)) | 3129 | temp-file-name)) |
| 3083 | 3130 | ||
| 3084 | (defconst python-shell-eval-setup-code | ||
| 3085 | "\ | ||
| 3086 | def __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 | 3131 | (defalias 'python-shell--encode-string |
| 3112 | (let ((fun (if (and (fboundp 'json-serialize) | 3132 | (let ((fun (if (and (fboundp 'json-serialize) |
| 3113 | (>= emacs-major-version 28)) | 3133 | (>= emacs-major-version 28)) |
| @@ -3128,12 +3148,11 @@ t when called interactively." | |||
| 3128 | (interactive | 3148 | (interactive |
| 3129 | (list (read-string "Python command: ") nil t)) | 3149 | (list (read-string "Python command: ") nil t)) |
| 3130 | (let ((process (or process (python-shell-get-process-or-error msg))) | 3150 | (let ((process (or process (python-shell-get-process-or-error msg))) |
| 3131 | (code (format "exec(%s);__PYTHON_EL_eval(%s, %s)\n" | 3151 | (code (format "__PYTHON_EL_eval(%s, %s)\n" |
| 3132 | (python-shell--encode-string python-shell-eval-setup-code) | ||
| 3133 | (python-shell--encode-string string) | 3152 | (python-shell--encode-string string) |
| 3134 | (python-shell--encode-string (or (buffer-file-name) | 3153 | (python-shell--encode-string (or (buffer-file-name) |
| 3135 | "<string>"))))) | 3154 | "<string>"))))) |
| 3136 | (if (<= (string-bytes code) 4096) | 3155 | (if (<= (string-bytes code) comint-max-line-length) |
| 3137 | (comint-send-string process code) | 3156 | (comint-send-string process code) |
| 3138 | (let* ((temp-file-name (with-current-buffer (process-buffer process) | 3157 | (let* ((temp-file-name (with-current-buffer (process-buffer process) |
| 3139 | (python-shell--save-temp-file string))) | 3158 | (python-shell--save-temp-file string))) |
| @@ -3180,8 +3199,7 @@ Return the output." | |||
| 3180 | (inhibit-quit t)) | 3199 | (inhibit-quit t)) |
| 3181 | (or | 3200 | (or |
| 3182 | (with-local-quit | 3201 | (with-local-quit |
| 3183 | (comint-send-string | 3202 | (python-shell-send-string string process) |
| 3184 | process (format "exec(%s)\n" (python-shell--encode-string string))) | ||
| 3185 | (while python-shell-output-filter-in-progress | 3203 | (while python-shell-output-filter-in-progress |
| 3186 | ;; `python-shell-output-filter' takes care of setting | 3204 | ;; `python-shell-output-filter' takes care of setting |
| 3187 | ;; `python-shell-output-filter-in-progress' to NIL after it | 3205 | ;; `python-shell-output-filter-in-progress' to NIL after it |
| @@ -3378,18 +3396,6 @@ t when called interactively." | |||
| 3378 | nil ;; noop | 3396 | nil ;; noop |
| 3379 | msg)))) | 3397 | msg)))) |
| 3380 | 3398 | ||
| 3381 | |||
| 3382 | (defconst python-shell-eval-file-setup-code | ||
| 3383 | "\ | ||
| 3384 | def __PYTHON_EL_eval_file(filename, tempname, encoding, delete): | ||
| 3385 | import codecs, os | ||
| 3386 | with codecs.open(tempname or filename, encoding=encoding) as file: | ||
| 3387 | source = file.read().encode(encoding) | ||
| 3388 | if delete and tempname: | ||
| 3389 | os.remove(tempname) | ||
| 3390 | return __PYTHON_EL_eval(source, filename)" | ||
| 3391 | "Code used to evaluate files in inferior Python processes.") | ||
| 3392 | |||
| 3393 | (defun python-shell-send-file (file-name &optional process temp-file-name | 3399 | (defun python-shell-send-file (file-name &optional process temp-file-name |
| 3394 | delete msg) | 3400 | delete msg) |
| 3395 | "Send FILE-NAME to inferior Python PROCESS. | 3401 | "Send FILE-NAME to inferior Python PROCESS. |
| @@ -3419,9 +3425,7 @@ t when called interactively." | |||
| 3419 | (comint-send-string | 3425 | (comint-send-string |
| 3420 | process | 3426 | process |
| 3421 | (format | 3427 | (format |
| 3422 | "exec(%s);exec(%s);__PYTHON_EL_eval_file(%s, %s, %s, %s)\n" | 3428 | "__PYTHON_EL_eval_file(%s, %s, %s, %s)\n" |
| 3423 | (python-shell--encode-string python-shell-eval-setup-code) | ||
| 3424 | (python-shell--encode-string python-shell-eval-file-setup-code) | ||
| 3425 | (python-shell--encode-string file-name) | 3429 | (python-shell--encode-string file-name) |
| 3426 | (python-shell--encode-string (or temp-file-name "")) | 3430 | (python-shell--encode-string (or temp-file-name "")) |
| 3427 | (python-shell--encode-string (symbol-name encoding)) | 3431 | (python-shell--encode-string (symbol-name encoding)) |