(defmacro elpy-shell--with-maybe-echo-output (body)
"Run BODY and grab shell output according to `elpy-shell-echo-output'.
This modifies the original function to check if shell is visible in other frames
"
`(cl-letf (((symbol-function 'python-shell-send-file)
(if elpy-shell-echo-output
(symbol-function 'elpy-shell-send-file)
(symbol-function 'python-shell-send-file))))
(let* ((process (elpy-shell--ensure-shell-running))
(process-buf (process-buffer process))
;; Check if the buffer is visible in any window of any frame
(shell-visible (or elpy-shell-display-buffer-after-send
(get-buffer-window-list process-buf nil t)))) ; Checks all frames
(with-current-buffer process-buf
(setq-local elpy-shell--capture-output
(and elpy-shell-echo-output
(or (not (eq elpy-shell-echo-output 'when-shell-not-visible))
(not (null shell-visible)))))) ; Properly check for visibility
(progn ,body))))
Here is how to make it work with multiple frames.