From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Jack Kamm Newsgroups: gmane.emacs.devel Subject: [PATCH] python.el: Returning inferior Python output without inhibiting it Date: Sun, 01 Oct 2023 09:05:23 -0700 Message-ID: <87msx2ib0c.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="8527"; mail-complaints-to="usenet@ciao.gmane.io" To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Oct 01 18:06:19 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qmyxW-0001rV-O8 for ged-emacs-devel@m.gmane-mx.org; Sun, 01 Oct 2023 18:06:18 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qmyws-0007rZ-Hr; Sun, 01 Oct 2023 12:05:39 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qmywn-0007rJ-RZ for emacs-devel@gnu.org; Sun, 01 Oct 2023 12:05:33 -0400 Original-Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qmywk-0001uk-08 for emacs-devel@gnu.org; Sun, 01 Oct 2023 12:05:32 -0400 Original-Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-693375d2028so5423911b3a.2 for ; Sun, 01 Oct 2023 09:05:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696176325; x=1696781125; darn=gnu.org; h=mime-version:message-id:date:subject:to:from:from:to:cc:subject :date:message-id:reply-to; bh=UhrO63NZuxo4/qeHJOitwX/o2KhdUg17j1Yy3ZDL2+Q=; b=kAmFHGTbPQ6dBhnANeovUuXC8XyT2tjmvgBYsjqfSj2iEPcDLMlvsTvqNHraBka1Mg duHpTFQTuMZ/4leOv+SBLAXX8wstCSKyUksJ/aRqePJKoIyn6pQ3BYgR28h2klaM3oBY 1rJ7kb7GYj8a9zC95DKcyIYoZ4ySsDI5ns5pjJXK7TbUOYVMJYhgbDJ12nmByByuOwDs 24LC2pTngr7Qk23yPJC8M36k04WUXViEnK4oDdgv7aQgjx14T2w/hlDoADXSyzRfCKRs xOYQd9ffwoJR5rdMThjciFnr+Y/++CgWXZi6YvkYg++c9Ca938gp8EZBwfhcrJtDRP8c /F+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696176325; x=1696781125; h=mime-version:message-id:date:subject:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=UhrO63NZuxo4/qeHJOitwX/o2KhdUg17j1Yy3ZDL2+Q=; b=W6JeAJuiY2DO2y9ZcCs4myioiLqIKRgjEikR7wlMC/bA/Z8/xs7h/M9kDj3gkQro7j QpDP7SuopTutdhuLFFDAC8FmR97QwEv+Hm8Kzj4DkywYLmUCIyon1Sisc3iCtpALDIaJ zpLLS8gtXZcV5gcOQ8cmJ6SdBN7cGjQAXUZIwPI2E+e8m/jfmzYZGuLOSfVKluDX9770 mBqikyvbVyAL12dT998AO9qV6DRgHU0CYoPfey+0xLyDKUNVpd307ZdvkY5WWBp06XI8 SqFW1kKRE1k7bGcM8CH2vlbD7tor17edbLWPZ9qz3EHn/E1FobrgVdJG3mHY/AortF2i h9bQ== X-Gm-Message-State: AOJu0YxR5DiabwqV6TykF3Om9EcXQ3gp4tAXosq0QrdYUTwGRgsnEHq4 laMolNw1v65eVpnyXib8sjaTqWOh7mk= X-Google-Smtp-Source: AGHT+IEbGhI0pA7Hy1+e4tw2PyFsR5wbOJjAuCa34c++yAPPACuxivXc0yQpJAXHLe/OgKZmcIj6tA== X-Received: by 2002:a05:6a00:1818:b0:691:320:b551 with SMTP id y24-20020a056a00181800b006910320b551mr11174393pfa.34.1696176324929; Sun, 01 Oct 2023 09:05:24 -0700 (PDT) Original-Received: from localhost (157-131-78-143.fiber.dynamic.sonic.net. [157.131.78.143]) by smtp.gmail.com with ESMTPSA id v16-20020aa78510000000b00666e649ca46sm18206605pfn.101.2023.10.01.09.05.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Oct 2023 09:05:24 -0700 (PDT) Received-SPF: pass client-ip=2607:f8b0:4864:20::42d; envelope-from=jackkamm@gmail.com; helo=mail-pf1-x42d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:311222 Archived-At: --=-=-= Content-Type: text/plain Hello, maintainer of ob-python.el in Org-mode here. It would be very useful to ob-python, if python.el had a function that evaluated Python code and returned output, without inhibiting the output. So, this patch modifies `python-shell-send-string-no-output', adding an argument to show the output. I also rename it to `python-shell-send-string-return-output' since that is a more accurate name for the new behavior. The motivation is that ob-python already implements this in `org-babel-python-send-string', but we have noticed occasional issues with leaky prompts in our CI [1], and suspect that the `python-shell-send-string-no-output' implementation may be more robust. Also, in Org-mode we have a long term goal to be more modular and integrate better with the rest of Emacs [2]; and replacing custom ob-python code with python.el functionality would help with that. [1] https://list.orgmode.org/873506j7ky.fsf@localhost/ [2] https://list.orgmode.org/orgmode/E1kIPh1-0001Lu-Rg@fencepost.gnu.org/ --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-python.el-Function-to-return-output-without-necessar.patch >From ffdbf2961c9d159b2c1d586667469cf7020240c2 Mon Sep 17 00:00:00 2001 From: Jack Kamm Date: Sat, 30 Sep 2023 21:04:12 -0700 Subject: [PATCH] python.el: Function to return output without necessarily inhibiting Rename `python-shell-send-string-no-output' to `python-shell-send-string-return-output', and add option to not inhibit the output. * lisp/progmodes/python.el (python-shell-output-filter-inhibit-output): Variable to determine whether output currently inhibited. (python-shell-comint-watch-for-first-prompt-output-filter, python-shell-internal-send-string, python-shell-completion-native-setup, python-shell-completion-get-completions, python-ffap-module-path, python-eldoc--get-doc-at-point): Replace `python-shell-send-string-no-output' with `python-shell-send-string-return-output'. (python-shell-send-string): Check `python-shell-output-filter-inhibit-output' instead of `python-shell-output-filter-in-progress' to determine whether output is inhibited. (python-shell-output-filter): Set `python-shell-output-filter-inhibit-output' to nil after reaching end of output. (python-shell-send-string-no-output): Obsolete function alias for `python-shell-send-string-return-output'. (python-shell-send-string-return-output): Rename from `python-shell-send-string-no-output'. Add function argument on whether output should be inhibited, and set `python-shell-output-filter-inhibit-output' accordingly. If not inhibited, then the original filter function is run in addition to `python-shell-output-filter', and `comint-last-prompt' is not reset after evaluation (since the original output filter will set it approriately). --- lisp/progmodes/python.el | 52 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index d3cb5a77e22..67a79192372 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -2736,6 +2736,7 @@ python-shell-dedicated (defvar python-shell-output-filter-in-progress nil) (defvar python-shell-output-filter-buffer nil) +(defvar python-shell-output-filter-inhibit-output nil) (defmacro python-shell--add-to-path-with-priority (pathvar paths) "Modify PATHVAR and ensure PATHS are added only once at beginning." @@ -3445,8 +3446,8 @@ python-shell-comint-watch-for-first-prompt-output-filter (format "exec(%s)\n" (python-shell--encode-string string)))))) ;; Bootstrap: the normal definition of `python-shell-send-string' ;; depends on the Python code sent here. - (python-shell-send-string-no-output python-shell-eval-setup-code) - (python-shell-send-string-no-output python-shell-eval-file-setup-code)) + (python-shell-send-string-return-output python-shell-eval-setup-code) + (python-shell-send-string-return-output python-shell-eval-file-setup-code)) (with-current-buffer (current-buffer) (let ((inhibit-quit nil)) (run-hooks 'python-shell-first-prompt-hook)))))) @@ -3750,7 +3751,7 @@ python-shell-send-string (python-shell--encode-string string) (python-shell--encode-string (or (buffer-file-name) ""))))) - (unless python-shell-output-filter-in-progress + (unless python-shell-output-filter-inhibit-output (with-current-buffer (process-buffer process) (save-excursion (goto-char (process-mark process)) @@ -3766,7 +3767,7 @@ python-shell-send-string (python-shell-send-file file-name process temp-file-name t))))) (defun python-shell-output-filter (string) - "Filter used in `python-shell-send-string-no-output' to grab output. + "Filter used in `python-shell-send-string-return-output' to grab output. STRING is the output received to this point from the process. This filter saves received output from the process in `python-shell-output-filter-buffer' and stops receiving it after @@ -3780,6 +3781,7 @@ python-shell-output-filter ;; Output ends when `python-shell-output-filter-buffer' contains ;; the prompt attached at the end of it. (setq python-shell-output-filter-in-progress nil + python-shell-output-filter-inhibit-output nil python-shell-output-filter-buffer (substring python-shell-output-filter-buffer 0 (match-beginning 0))) @@ -3792,15 +3794,23 @@ python-shell-output-filter (substring python-shell-output-filter-buffer (match-end 0))))) "") -(defun python-shell-send-string-no-output (string &optional process) - "Send STRING to PROCESS and inhibit output. -Return the output." +(define-obsolete-function-alias + 'python-shell-send-string-no-output + #'python-shell-send-string-return-output "30.1") + +(defun python-shell-send-string-return-output (string &optional process show-output) + "Send STRING to PROCESS and return the output. +Inhibit printing the output unless SHOW-OUTPUT is non-nil." (or process (setq process (python-shell-get-process-or-error))) - (cl-letf* (((process-filter process) + (cl-letf* ((original-filter-fn (process-filter process)) + ((process-filter process) (lambda (_proc str) (with-current-buffer (process-buffer process) - (python-shell-output-filter str)))) + (python-shell-output-filter str)) + (when show-output + (funcall original-filter-fn process str)))) (python-shell-output-filter-in-progress t) + (python-shell-output-filter-inhibit-output (not show-output)) (inhibit-quit t) (buffer (process-buffer process)) (last-prompt (cond ((boundp 'comint-last-prompt-overlay) @@ -3812,13 +3822,15 @@ python-shell-send-string-no-output (with-local-quit (unwind-protect (python-shell-send-string string process) - (when (not (null last-prompt)) - (with-current-buffer buffer - (set last-prompt last-prompt-value)))) + (unless show-output + (when (not (null last-prompt)) + (with-current-buffer buffer + (set last-prompt last-prompt-value))))) (while python-shell-output-filter-in-progress ;; `python-shell-output-filter' takes care of setting - ;; `python-shell-output-filter-in-progress' to NIL after it - ;; detects end of output. + ;; `python-shell-output-filter-in-progress' and + ;; `python-shell-output-filter-inhibit-output' to NIL after + ;; it detects end of output. (accept-process-output process)) (prog1 python-shell-output-filter-buffer @@ -3828,11 +3840,11 @@ python-shell-send-string-no-output (defun python-shell-internal-send-string (string) "Send STRING to the Internal Python interpreter. -Returns the output. See `python-shell-send-string-no-output'." +Returns the output. See `python-shell-send-string-return-output'." ;; XXX Remove `python-shell-internal-last-output' once CEDET is ;; updated to support this new mode. (setq python-shell-internal-last-output - (python-shell-send-string-no-output + (python-shell-send-string-return-output ;; Makes this function compatible with the old ;; python-send-receive. (At least for CEDET). (replace-regexp-in-string "_emacs_out +" "" string) @@ -4217,7 +4229,7 @@ python-shell-completion-native-try (defun python-shell-completion-native-setup () "Try to setup native completion, return non-nil on success." (let* ((process (python-shell-get-process)) - (output (python-shell-send-string-no-output " + (output (python-shell-send-string-return-output " def __PYTHON_EL_native_completion_setup(): try: import readline @@ -4454,7 +4466,7 @@ python-shell-completion-get-completions (with-current-buffer (process-buffer process) (let ((completions (python-util-strip-string - (python-shell-send-string-no-output + (python-shell-send-string-return-output (format "%s\nprint(';'.join(__PYTHON_EL_get_completions(%s)))" python-shell-completion-setup-code @@ -5198,7 +5210,7 @@ python-ffap-module-path (ready (python-shell-with-shell-buffer (python-util-comint-end-of-output-p))) (module-file - (python-shell-send-string-no-output + (python-shell-send-string-return-output (format "%s\nprint(__FFAP_get_module_path(%s))" python-ffap-setup-code (python-shell--encode-string module))))) @@ -5327,7 +5339,7 @@ python-eldoc--get-doc-at-point ;; Prevent resizing the echo area when iPython is ;; enabled. Bug#18794. (python-util-strip-string - (python-shell-send-string-no-output + (python-shell-send-string-return-output (format "%s\nprint(__PYDOC_get_help(%s))" python-eldoc-setup-code -- 2.42.0 --=-=-=--