Subject: bug#57184: [PATCH] Assorted improvements to python.el

From: Augusto Stoffel <[email-masked]>
Date: Sat, 13 Aug 2022 19:06:10 +0200

I have attached a sequence of patches with assorted small(ish)
improvements to python.el.

I hope this is a suitable format for review; let me know otherwise.

>From c68623c2da14ae436276c84ae3705f1708e2bd92 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <[email-masked]>
Date: Sat, 13 Aug 2022 17:04:17 +0200
Subject: [PATCH 1/4] python-check-command: don't use absolute executable names

This is incompatible with Tramp and packages that switch between
virtualenvs.

* lisp/progmodes/python.el (python-check-command): don't use absolute
executable names.
---
 lisp/progmodes/python.el | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 96f9d14832..3176d12bd1 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4702,9 +4702,9 @@ ffap-alist
 ;;; Code check
 
 (defcustom python-check-command
-  (or (executable-find "pyflakes")
-      (executable-find "epylint")
-      "install pyflakes, pylint or something else")
+  (cond ((executable-find "pyflakes") "pyflakes")
+        ((executable-find "epylint") "epylint")
+        (t "pyflakes"))
   "Command used to check a Python file."
   :type 'string)
 
-- 
2.37.1

>From d0f754b3d39a8189ba6cc2d09aea0973f79f4ca6 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <[email-masked]>
Date: Sat, 13 Aug 2022 17:39:57 +0200
Subject: [PATCH 2/4] python.el: Adjustments to Flymake backend

* lisp/progmodes/python (python-flymake-command): Advertise possiblity
to use pylint.
(python-flymake-command-output-pattern): Make compatible with pyflakes
version 2.4.0
---
 lisp/progmodes/python.el | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 3176d12bd1..be1d3aab00 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -5625,9 +5625,13 @@ python-flymake-command
 This is a non empty list of strings, the checker tool possibly followed by
 required arguments.  Once launched it will receive the Python source to be
 checked as its standard input.
-To use `flake8' you would set this to (\"flake8\" \"-\")."
+To use `flake8' you would set this to (\"flake8\" \"-\").
+To use `pylint' you would set this to (\"pylint\" \"--from-stdin\" \"stdin\")."
   :version "26.1"
-  :type '(repeat string))
+  :type '(choice (const :tag "Pyflakes" ("pyflakes"))
+                 (const :tag "Flake8" ("flake8" "-"))
+                 (const :tag "Pylint" ("pylint" "--from-stdin" "stdin"))
+                 (repeat :tag "Custom command" string)))
 
 ;; The default regexp accommodates for older pyflakes, which did not
 ;; report the column number, and at the same time it's compatible with
@@ -5635,7 +5639,7 @@ python-flymake-command
 ;; TYPE
 (defcustom python-flymake-command-output-pattern
   (list
-   "^\\(?:<?stdin>?\\):\\(?1:[0-9]+\\):\\(?:\\(?2:[0-9]+\\):\\)? \\(?3:.*\\)$"
+   "^\\(?:<?stdin>?\\):\\(?1:[0-9]+\\):\\(?:\\(?2:[0-9]+\\):?\\)? \\(?3:.*\\)$"
    1 2 nil 3)
   "Specify how to parse the output of `python-flymake-command'.
 The value has the form (REGEXP LINE COLUMN TYPE MESSAGE): if
-- 
2.37.1

>From 95675a3f63bc420813992d7b599e99b303e4fd63 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <[email-masked]>
Date: Sat, 13 Aug 2022 18:10:14 +0200
Subject: [PATCH 3/4] python.el: Add completion-predicate symbol property to
 commands

* lisp/progmodes/python.el: Add a completion-predicate property to
most commands defined in this file; some are only useful in
python-mode, others in inferior-python mode as well.
(python-skeleton-define, python-define-auxiliary-skeleton): Add
appropriate completion-predicate properties.
---
 lisp/progmodes/python.el | 75 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 67 insertions(+), 8 deletions(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index be1d3aab00..163bae07c2 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4546,8 +4546,13 @@ python-skeleton-define
 be added to `python-mode-skeleton-abbrev-table'."
   (declare (indent 2))
   (let* ((name (symbol-name name))
-         (function-name (intern (concat "python-skeleton-" name))))
+         (function-name (intern (concat "python-skeleton-" name)))
+         (completion-predicate (lambda (_ buffer)
+                                 (provided-mode-derived-p
+                                  (buffer-local-value 'major-mode buffer)
+                                  'python-mode))))
     `(progn
+       (put ',function-name 'completion-predicate ,completion-predicate)
        (define-abbrev python-mode-skeleton-abbrev-table
          ,name "" ',function-name :system t)
        (setq python-skeleton-available
@@ -4573,13 +4578,15 @@ python-define-auxiliary-skeleton
       (setq skel
             `(< ,(format "%s:" name) \n \n
                 > _ \n)))
-    `(define-skeleton ,function-name
-       ,(or doc
-            (format "Auxiliary skeleton for %s statement." name))
-       nil
-       (unless (y-or-n-p ,msg)
-         (signal 'quit t))
-       ,@skel)))
+    `(progn
+       (put ',function-name 'completion-predicate #'ignore)
+       (define-skeleton ,function-name
+         ,(or doc
+              (format "Auxiliary skeleton for %s statement." name))
+         nil
+         (unless (y-or-n-p ,msg)
+           (signal 'quit t))
+         ,@skel))))
 
 (python-define-auxiliary-skeleton else)
 
@@ -5864,6 +5871,58 @@ python-mode
 
   (add-hook 'flymake-diagnostic-functions #'python-flymake nil t))
 
+;;; Completion predicates for M-x
+(dolist (sym '(python-check
+               python-fill-paragraph
+               python-indent-dedent-line
+               python-indent-dedent-line-backspace
+               python-indent-guess-indent-offset
+               python-indent-shift-left
+               python-indent-shift-right
+               python-mark-defun
+               python-nav-backward-block
+               python-nav-backward-defun
+               python-nav-backward-sexp
+               python-nav-backward-sexp-safe
+               python-nav-backward-statement
+               python-nav-backward-up-list
+               python-nav-beginning-of-block
+               python-nav-beginning-of-statement
+               python-nav-end-of-block
+               python-nav-end-of-defun
+               python-nav-end-of-statement
+               python-nav-forward-block
+               python-nav-forward-defun
+               python-nav-forward-sexp
+               python-nav-forward-sexp-safe
+               python-nav-forward-statement
+               python-nav-if-name-main
+               python-nav-up-list
+               python-shell-send-buffer
+               python-shell-send-defun
+               python-shell-send-statement))
+  (put sym 'completion-predicate (lambda (_ buffer)
+                                   (provided-mode-derived-p
+                                    (buffer-local-value 'major-mode buffer)
+                                    'python-mode))))
+
+(dolist (sym '(python-describe-at-point
+               python-eldoc-at-point
+               python-shell-completion-native-toggle
+               python-shell-completion-native-turn-off
+               python-shell-completion-native-turn-on
+               python-shell-completion-native-turn-on-maybe
+               python-shell-font-lock-cleanup-buffer
+               python-shell-font-lock-toggle
+               python-shell-font-lock-turn-off
+               python-shell-font-lock-turn-on
+               python-shell-package-enable
+               python-shell-completion-complete-or-indent  ))
+  (put sym 'completion-predicate (lambda (_ buffer)
+                                   (provided-mode-derived-p
+                                    (buffer-local-value 'major-mode buffer)
+                                    'python-mode 'inferior-python-mode))))
+
 (provide 'python)
 
 ;;; python.el ends here
-- 
2.37.1

>From 97895f6c5afcd2c0236185ff406c3d4261fbc567 Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <[email-masked]>
Date: Sat, 13 Aug 2022 18:55:48 +0200
Subject: [PATCH 4/4] python-mode: Remove special outline-heading-end-regexp

It doesn't work well with the new type annotation syntax introduced in
Python 3.5, see bug#53913.

* lisp/progmodes/python.el (python-mode): remove buffer-local setting
of outline-heading-end-regexp.
---
 lisp/progmodes/python.el | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 163bae07c2..8cd654ce14 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -5854,7 +5854,6 @@ python-mode
      nil))
 
   (setq-local outline-regexp (python-rx (* space) block-start))
-  (setq-local outline-heading-end-regexp ":[^\n]*\n")
   (setq-local outline-level
               (lambda ()
                 "`outline-level' function for Python mode."
-- 
2.37.1