Package: emacs;
Reported by: Lele Gaifax <lele <at> metapensiero.it>
Date: Fri, 13 Oct 2017 09:55:02 UTC
Severity: wishlist
Tags: fixed, patch
Fixed in version 26.1
Done: joaotavora <at> gmail.com (João Távora)
Bug is archived. No further changes may be made.
Message #17 received at 28808 <at> debbugs.gnu.org (full text, mbox):
From: Lele Gaifax <lele <at> metapensiero.it> To: João Távora <joaotavora <at> gmail.com> Cc: 28808 <at> debbugs.gnu.org Subject: Re: bug#28808: [PATCH] Implement Python backend for Flymake Date: Tue, 17 Oct 2017 23:58:08 +0200
[Message part 1 (text/plain, inline)]
Hi João, I think I fulfilled all your suggestions/requests, and thus I'm re-attaching the current version of the backend. Please let me know if there's something more I can do, I will happily keep hacking! ciao, lele.
[0001-Add-a-Flymake-backend-for-Python.patch (text/x-diff, inline)]
From 4e61fa030704a5e7bfcd537c503cef1da4409b6b Mon Sep 17 00:00:00 2001 From: Lele Gaifax <lele <at> metapensiero.it> Date: Fri, 13 Oct 2017 10:44:02 +0200 Subject: [PATCH] Add a Flymake backend for Python * lisp/progmodes/python.el: Implement new Flymake backend with related customizable settings. (python-flymake-command, python-flymake-command-output-regexp, python-flymake-msg-alist): New defcustom. (python-flymake): New function. (python-flymake-activate): New function. --- lisp/progmodes/python.el | 135 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 895117b9ee..831fd7e7f2 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -5142,6 +5142,141 @@ python-util-valid-regexp-p (ignore-errors (string-match regexp "") t)) +;;; Flymake integration + +(defgroup python-flymake nil + "Integration between Python and Flymake." + :group 'python + :link '(custom-group-link :tag "Flymake" flymake) + :version "26.1") + +(defcustom python-flymake-command '("pyflakes") + "The external tool that will be used to perform the syntax check. +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\" \"-\")." + :group 'python-flymake + :type '(repeat string)) + +;; The default regexp accomodates for older pyflakes, which did not +;; report the column number, and at the same time it's compatible with +;; flake8 output, although it may be redefined to explicitly match the +;; TYPE +(defcustom python-flymake-command-output-regexp + (list + "^\\(?:<?stdin>?\\):\\(?1:[0-9]+\\):\\(?:\\(?2:[0-9]+\\):\\)? \\(?3:.*\\)$" + 1 2 nil 3) + "Specify how to parse the output of the specified tool. +The value has the form (REGEXP LINE COLUMN TYPE MESSAGE): if +REGEXP matches, the LINE'th subexpression gives the line number, +the COLUMN'th subexpression gives the column number on that line, +the TYPE'th subexpression gives the type of the message and +MESSAGE'th is the message text itself. + +If COLUMN or TYPE are nil or that index didn't match, that +information is not present on the matched line and a default will +be used." + :group 'python-flymake + :type '(list regexp + (integer :tag "Line's index") + (choice + (const :tag "No column" nil) + (integer :tag "Column's index")) + (choice + (const :tag "No type" nil) + (integer :tag "Type's index")) + (integer :tag "Message's index"))) + +(defcustom python-flymake-msg-alist + '(("\\(^redefinition\\|.*unused.*\\|used$\\)" . :warning)) + "Alist used to associate messages to their types. +Each element should be a cons-cell (REGEXP . TYPE), where TYPE must be +one defined in the variable `flymake-diagnostic-types-alist'. +For example, when using `flake8' a possible configuration could be: + + ((\"\\(^redefinition\\|.*unused.*\\|used$\\)\" . :warning) + (\"^E999\" . :error) + (\"^[EW][0-9]+\" . :note)) + +By default messages are considered errors." + :group 'python-flymake + :type `(alist :key-type (regexp) + :value-type (symbol))) + +(defvar-local python--flymake-proc nil) + +(defun python--flymake-parse-output (source proc report-fn) + "Collect diagnostics parsing checker tool's output line by line." + (let ((rx (nth 0 python-flymake-command-output-regexp)) + (lineidx (nth 1 python-flymake-command-output-regexp)) + (colidx (nth 2 python-flymake-command-output-regexp)) + (typeidx (nth 3 python-flymake-command-output-regexp)) + (msgidx (nth 4 python-flymake-command-output-regexp))) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp rx nil t) + for msg = (match-string msgidx) + for (beg . end) = (flymake-diag-region + source + (string-to-number + (match-string lineidx)) + (and colidx + (match-string colidx) + (string-to-number + (match-string colidx)))) + for type = (or (and typeidx + (match-string typeidx) + (assoc-default + (match-string typeidx) + python-flymake-msg-alist + #'string-match)) + (assoc-default msg + python-flymake-msg-alist + #'string-match) + :error) + collect (flymake-make-diagnostic + source beg end type msg) + into diags + finally (funcall report-fn diags))))) + +(defun python-flymake (report-fn &rest _args) + "Flymake backend for Python. +This backend uses `python-flymake-command' (which see) to launch a process +that is passed the current buffer's content via stdin. +REPORT-FN is Flymake's callback function." + (unless (executable-find (car python-flymake-command)) + (error "Cannot find a suitable checker")) + + (when (process-live-p python--flymake-proc) + (kill-process python--flymake-proc)) + + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq python--flymake-proc + (make-process + :name "python-flymake" + :noquery t + :connection-type 'pipe + :buffer (generate-new-buffer " *python-flymake*") + :command python-flymake-command + :sentinel + (lambda (proc _event) + (when (eq 'exit (process-status proc)) + (unwind-protect + (when (eq proc python--flymake-proc) + (python--flymake-parse-output source proc report-fn)) + (kill-buffer (process-buffer proc))))))) + (process-send-region python--flymake-proc (point-min) (point-max)) + (process-send-eof python--flymake-proc)))) + +(defun python-flymake-activate () + "Activate the Flymake syntax check on all python-mode buffers." + (add-hook 'flymake-diagnostic-functions #'python-flymake nil t)) + + (defun python-electric-pair-string-delimiter () (when (and electric-pair-mode (memq last-command-event '(?\" ?\')) -- 2.15.0.rc1
[Message part 3 (text/plain, inline)]
-- nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia. lele <at> metapensiero.it | -- Fortunato Depero, 1929.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.