branch: elpa/flymake-pyrefly commit bb72e8c622d464136f5388c3df5ff9a1d091fbb3 Merge: 5e6800f88f c4611b7be4 Author: Boris Shminke <1696493+inpef...@users.noreply.github.com> Commit: GitHub <nore...@github.com>
Merge pull request #21 from inpefess/7-apply-patch Apply patch --- flymake-pyrefly.el | 48 +++++++++++++++++++++++++------------------ tests/test-flymake-pyrefly.el | 8 ++++---- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/flymake-pyrefly.el b/flymake-pyrefly.el index a9f600c7d6..4e84ec3422 100644 --- a/flymake-pyrefly.el +++ b/flymake-pyrefly.el @@ -1,10 +1,11 @@ ;;; flymake-pyrefly.el --- A Pyrefly Flymake backend -*- lexical-binding: t; -*- ;; Copyright (C) 2025 Free Software Foundation, Inc. + ;; Author: Boris Shminke <bo...@shminke.com> ;; Maintainer: Boris Shminke <bo...@shminke.com> ;; Created: 29 Jun 2025 -;; Version: 0.1.0 +;; Version: 0.1.1 ;; Keywords: tools, languages ;; URL: https://github.com/inpefess/flymake-pyrefly ;; Package-Requires: ((emacs "26.1")) @@ -25,8 +26,12 @@ ;; along with this program. If not, see <https://www.gnu.org/licenses/>. ;;; Commentary: + +;; A Pyrefly (https://pyrefly.org/) Flymake backend. ;; Based on the annotated example from Flymake info. +;; ;; Usage: +;; ;; (use-package flymake-pyrefly ;; :hook (python-mode . pyrefly-setup-flymake-backend)) @@ -34,62 +39,66 @@ (require 'cl-lib) (defvar-local pyrefly--flymake-proc nil) -(defun flymake-pyrefly (report-fn &rest _args) +(defun pyrefly-flymake-backend (report-fn &rest _args) "Report pyrefly diagnostic with REPORT-FN." ;; Not having pyrefly installed is a serious problem which should cause ;; the backend to disable itself, so an error is signaled. - ;; - (unless (executable-find - "pyrefly") (error "Cannot find pyrefly")) + (unless (executable-find "pyrefly") + (error "Cannot find pyrefly")) + ;; If a live process launched in an earlier check was found, that ;; process is killed. When that process's sentinel eventually runs, ;; it will notice its obsoletion, since it have since reset ;; `flymake-pyrefly-proc' to a different value - ;; (when (process-live-p pyrefly--flymake-proc) (kill-process pyrefly--flymake-proc)) ;; Save the current buffer, the narrowing restriction, remove any ;; narrowing restriction. - ;; (let ((source (current-buffer)) (source-file-name buffer-file-name)) (save-restriction (widen) ;; Reset the `pyrefly--flymake-proc' process to a new process ;; calling the pyrefly tool. - ;; (setq pyrefly--flymake-proc (make-process :name "flymake-pyrefly" :noquery t :connection-type 'pipe ;; Make output go to a temporary buffer. - ;; :buffer (generate-new-buffer " *flymake-pyrefly*") :command - (append - '("pyrefly" "check" "--output-format" "min-text" "--no-summary") - (list source-file-name)) + `("pyrefly" "check" "--output-format" "min-text" "--no-summary" ,source-file-name) :sentinel (lambda (proc _event) ;; Check that the process has indeed exited, as it might ;; be simply suspended. - ;; (when (memq (process-status proc) '(exit signal)) (unwind-protect ;; Only proceed if `proc' is the same as ;; `pyrefly--flymake-proc', which indicates that ;; `proc' is not an obsolete process. - ;; (if (with-current-buffer source (eq proc pyrefly--flymake-proc)) (with-current-buffer (process-buffer proc) (goto-char (point-min)) ;; Parse the output buffer for diagnostic's ;; messages and locations, collect them in a list ;; of objects, and call `report-fn'. - ;; (cl-loop while (search-forward-regexp - "^\\([A-Z]+\\) .+\.py:\\([0-9]+\\):\\([0-9]+\\)\-\\([0-9]+\\): \\(.*\\)$" + (rx line-start + ;; diagnostic level (error, warn, etc) + (group (one-or-more upper-case)) + ;; file name + (one-or-more anything) ".py:" + ;; line number + (group (one-or-more digit)) ":" + ;; start column + (group (one-or-more digit)) "-" + ;; end column + (group (one-or-more digit)) ": " + ;; diagnostic message + (group (one-or-more anything)) + line-end) nil t) for msg = (match-string 5) for beg = (cons (string-to-number (match-string 2)) @@ -99,7 +108,6 @@ for type = (if (equal "ERROR" (match-string 1)) :error :warning) - when (and beg end) collect (flymake-make-diagnostic source-file-name beg end @@ -111,16 +119,16 @@ proc)) ;; Cleanup the temporary buffer used to hold the ;; check's output. - ;; (kill-buffer (process-buffer proc))))))) ;; Send the buffer contents to the process's stdin, followed by ;; an EOF. - ;; (process-send-region pyrefly--flymake-proc (point-min) (point-max)) (process-send-eof pyrefly--flymake-proc)))) +;;;###autoload (defun pyrefly-setup-flymake-backend () "Setup Pyrefly as Flymake backend." - (add-hook 'flymake-diagnostic-functions 'flymake-pyrefly nil t)) + (add-hook 'flymake-diagnostic-functions #'pyrefly-flymake-backend nil t)) + (provide 'flymake-pyrefly) ;;; flymake-pyrefly.el ends here diff --git a/tests/test-flymake-pyrefly.el b/tests/test-flymake-pyrefly.el index 3e7ce13ba4..dc7a5f08a0 100644 --- a/tests/test-flymake-pyrefly.el +++ b/tests/test-flymake-pyrefly.el @@ -24,7 +24,7 @@ (ert-deftest flymake-pyrefly-test-no-pyrefly () "Test error message when Pyrefly is not found." (find-file "tests/example.py") - (should-error (flymake-pyrefly 'identity))) + (should-error (pyrefly-flymake-backend 'identity))) (ert-deftest flymake-pyrefly-test-normal-use-case () "Test a normal Pyrefly use-case." (defun mock-report-fn (args) @@ -32,14 +32,14 @@ (push (getenv "PYREFLY_BIN_DIR") exec-path) (find-file "tests/example.py") (setq saved-args nil) - (flymake-pyrefly 'mock-report-fn) - (flymake-pyrefly 'mock-report-fn) + (pyrefly-flymake-backend 'mock-report-fn) + (pyrefly-flymake-backend 'mock-report-fn) (sleep-for 1) (pop exec-path) (should (equal (aref (car saved-args) 2) (cons 2 5)))) (ert-deftest flymake-pyrefly-test-setup () (pyrefly-setup-flymake-backend) - (should (member 'flymake-pyrefly flymake-diagnostic-functions))) + (should (member 'pyrefly-flymake-backend flymake-diagnostic-functions))) (provide 'test-flymake-pyrefly) ;;; test-flymake-pyrefly.el ends here