Function: python-fix-imports

python-fix-imports is an autoloaded, interactive and byte-compiled function defined in python.el.gz.

Signature

(python-fix-imports)

Documentation

Add missing imports and remove unused ones from the current buffer.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/python.el.gz
;;;###autoload
(defun python-fix-imports ()
  "Add missing imports and remove unused ones from the current buffer."
  (interactive)
  (let ((buffer (current-buffer))
        undefined unused add remove)
    ;; Compute list of undefined and unused names
    (with-temp-buffer
      (let ((temp (current-buffer)))
        (with-current-buffer buffer
          (call-process-region (point-min) (point-max)
                               python-interpreter
                               nil temp nil
                               "-m" "pyflakes"))
        (goto-char (point-min))
        (when (looking-at-p ".* No module named pyflakes$")
          (error "%s couldn't find pyflakes" python-interpreter))
        (while (not (eobp))
          (cond ((looking-at ".* undefined name '\\([^']+\\)'$")
                 (push (match-string 1) undefined))
                ((looking-at ".*'\\([^']+\\)' imported but unused$")
                 (push (match-string 1) unused)))
	  (forward-line 1))))
    ;; Compute imports to be added
    (dolist (name (seq-uniq undefined))
      (when-let ((statement (python--query-import name
                                                  (python--import-sources)
                                                  (format "\
Add import for undefined name `%s' (empty to skip): "
                                                          name))))
        (push statement add)))
    ;; Compute imports to be removed
    (dolist (name (seq-uniq unused))
      ;; The unused imported names, as provided by pyflakes, are of
      ;; the form "module.var" or "module.var as alias", independently
      ;; of style of import statement used.
      (let* ((filter
              (lambda (statement)
                (string= name
                         (thread-last
                           statement
                           (replace-regexp-in-string "^\\(from\\|import\\) " "")
                           (replace-regexp-in-string " import " ".")))))
             (statements (seq-filter filter (python--list-imports nil buffer))))
        (when (length= statements 1)
          (push (car statements) remove))))
    ;; Edit buffer and say goodbye
    (if (not (or add remove))
        (message "(No changes in Python imports needed)")
      (apply #'python--do-isort
             (append (mapcan (lambda (x) (list "--add" x)) add)
                     (mapcan (lambda (x) (list "--rm" x)) remove)))
      (message "%s" (concat (when add "Added ")
                            (when add (string-join add ", "))
                            (when remove (if add " and removed " "Removed "))
                            (when remove (string-join remove ", " )))))))