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.

If there are missing imports, ask for an import statement using all imports found in the current project as suggestions. If there is only one such suggestion, act without asking.

If the buffer does not belong to a project, the import statement is searched under the buffer's default directory. For example, if the file is located directly under the home directory, all files under the home directory will be searched. Please note that this can take a long time and may appear to hang.

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.

If there are missing imports, ask for an import statement using all
imports found in the current project as suggestions.  If there is only
one such suggestion, act without asking.

If the buffer does not belong to a project, the import statement is
searched under the buffer's default directory.  For example, if the file
is located directly under the home directory, all files under the home
directory will be searched.  Please note that this can take a long time
and may appear to hang."
  (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
          (apply #'call-process-region
                  (point-min) (point-max)
                  python-interpreter
                  nil temp nil
                  (append
                   (split-string-shell-command
                    python-interpreter-args)
                   '("-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 ", " )))))))