aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorStefan Monnier2022-02-04 13:35:21 -0500
committerStefan Monnier2022-02-04 13:35:38 -0500
commitd340dc0a256db979c617bd5ee06dafa5a52791f5 (patch)
tree3bc7de8ee06f91ee0d1b135f354ecdee03fb6491 /lisp/progmodes/python.el
parentf88d4e424877c5709bb49d7d905004dea06ce089 (diff)
downloademacs-d340dc0a256db979c617bd5ee06dafa5a52791f5.tar.gz
emacs-d340dc0a256db979c617bd5ee06dafa5a52791f5.zip
python.el: Try and better split the Tramp code
Massage the Python-Tramp code so that the Tramp part and the Python part are a bit less intertwined. It's still not quite right, but it's a bit closer to the point where the Tramp part can be moved to `tramp.el`. * lisp/progmodes/python.el: Don't require `tramp-sh`. Do require `subr-x` OTOH. Remove redundant `:group`s. (python-shell--calculate-process-environment): New function, that only return the entries to be added. (python-shell-calculate-process-environment): Rewrite and declare obsolete. (python-shell-tramp-refresh-remote-path) (python-shell-tramp-refresh-process-environment): Silence compiler warnings. (python-shell-with-environment): Move the bulk of its code to a new function `python-shell--with-environment` for easier debugging and to avoid code duplication. (python-shell--with-environment): New function. Split the Tramp case into its own function. (python-shell--tramp-with-environment): New function. (python-eldoc-function-timeout-permanent): Fix doc's first line. * test/lisp/progmodes/python-tests.el: Adjust accordingly. (python-shell-calculate-process-environment-1) (python-shell-calculate-process-environment-2) (python-shell-calculate-process-environment-3) (python-shell-calculate-process-environment-4) (python-shell-calculate-process-environment-5) (python-shell-calculate-process-environment-6) (python-shell-calculate-process-environment-7) (python-shell-calculate-process-environment-8): Use `python-shell--calculate-process-environment`. (python--tests-process-env-canonical, python--tests-process-env-eql): New functions. (python-shell-with-environment-2, python-shell-with-environment-3): Use them.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el322
1 files changed, 157 insertions, 165 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 5889f2ab670..ba8e3e811d4 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -92,7 +92,7 @@
92;; Operating Systems' pipe buffering (e.g. CPython 3.3.4 in Windows 7. 92;; Operating Systems' pipe buffering (e.g. CPython 3.3.4 in Windows 7.
93;; See URL `https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304'). To 93;; See URL `https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304'). To
94;; avoid this, the `python-shell-unbuffered' defaults to non-nil and 94;; avoid this, the `python-shell-unbuffered' defaults to non-nil and
95;; controls whether `python-shell-calculate-process-environment' 95;; controls whether `python-shell--calculate-process-environment'
96;; should set the "PYTHONUNBUFFERED" environment variable on startup: 96;; should set the "PYTHONUNBUFFERED" environment variable on startup:
97;; See URL `https://docs.python.org/3/using/cmdline.html#cmdoption-u'. 97;; See URL `https://docs.python.org/3/using/cmdline.html#cmdoption-u'.
98 98
@@ -149,7 +149,7 @@
149;; (setq python-shell-process-environment 149;; (setq python-shell-process-environment
150;; (list 150;; (list
151;; (format "PATH=%s" (mapconcat 151;; (format "PATH=%s" (mapconcat
152;; 'identity 152;; #'identity
153;; (reverse 153;; (reverse
154;; (cons (getenv "PATH") 154;; (cons (getenv "PATH")
155;; '("/path/to/env/bin/"))) 155;; '("/path/to/env/bin/")))
@@ -245,7 +245,7 @@
245(require 'ansi-color) 245(require 'ansi-color)
246(require 'cl-lib) 246(require 'cl-lib)
247(require 'comint) 247(require 'comint)
248(require 'tramp-sh) 248(eval-when-compile (require 'subr-x)) ;For `string-empty-p'.
249 249
250;; Avoid compiler warnings 250;; Avoid compiler warnings
251(defvar view-return-to-alist) 251(defvar view-return-to-alist)
@@ -273,39 +273,39 @@
273(defvar python-mode-map 273(defvar python-mode-map
274 (let ((map (make-sparse-keymap))) 274 (let ((map (make-sparse-keymap)))
275 ;; Movement 275 ;; Movement
276 (define-key map [remap backward-sentence] 'python-nav-backward-block) 276 (define-key map [remap backward-sentence] #'python-nav-backward-block)
277 (define-key map [remap forward-sentence] 'python-nav-forward-block) 277 (define-key map [remap forward-sentence] #'python-nav-forward-block)
278 (define-key map [remap backward-up-list] 'python-nav-backward-up-list) 278 (define-key map [remap backward-up-list] #'python-nav-backward-up-list)
279 (define-key map [remap mark-defun] 'python-mark-defun) 279 (define-key map [remap mark-defun] #'python-mark-defun)
280 (define-key map "\C-c\C-j" 'imenu) 280 (define-key map "\C-c\C-j" #'imenu)
281 ;; Indent specific 281 ;; Indent specific
282 (define-key map "\177" 'python-indent-dedent-line-backspace) 282 (define-key map "\177" #'python-indent-dedent-line-backspace)
283 (define-key map (kbd "<backtab>") 'python-indent-dedent-line) 283 (define-key map (kbd "<backtab>") #'python-indent-dedent-line)
284 (define-key map "\C-c<" 'python-indent-shift-left) 284 (define-key map "\C-c<" #'python-indent-shift-left)
285 (define-key map "\C-c>" 'python-indent-shift-right) 285 (define-key map "\C-c>" #'python-indent-shift-right)
286 ;; Skeletons 286 ;; Skeletons
287 (define-key map "\C-c\C-tc" 'python-skeleton-class) 287 (define-key map "\C-c\C-tc" #'python-skeleton-class)
288 (define-key map "\C-c\C-td" 'python-skeleton-def) 288 (define-key map "\C-c\C-td" #'python-skeleton-def)
289 (define-key map "\C-c\C-tf" 'python-skeleton-for) 289 (define-key map "\C-c\C-tf" #'python-skeleton-for)
290 (define-key map "\C-c\C-ti" 'python-skeleton-if) 290 (define-key map "\C-c\C-ti" #'python-skeleton-if)
291 (define-key map "\C-c\C-tm" 'python-skeleton-import) 291 (define-key map "\C-c\C-tm" #'python-skeleton-import)
292 (define-key map "\C-c\C-tt" 'python-skeleton-try) 292 (define-key map "\C-c\C-tt" #'python-skeleton-try)
293 (define-key map "\C-c\C-tw" 'python-skeleton-while) 293 (define-key map "\C-c\C-tw" #'python-skeleton-while)
294 ;; Shell interaction 294 ;; Shell interaction
295 (define-key map "\C-c\C-p" 'run-python) 295 (define-key map "\C-c\C-p" #'run-python)
296 (define-key map "\C-c\C-s" 'python-shell-send-string) 296 (define-key map "\C-c\C-s" #'python-shell-send-string)
297 (define-key map "\C-c\C-e" 'python-shell-send-statement) 297 (define-key map "\C-c\C-e" #'python-shell-send-statement)
298 (define-key map "\C-c\C-r" 'python-shell-send-region) 298 (define-key map "\C-c\C-r" #'python-shell-send-region)
299 (define-key map "\C-\M-x" 'python-shell-send-defun) 299 (define-key map "\C-\M-x" #'python-shell-send-defun)
300 (define-key map "\C-c\C-c" 'python-shell-send-buffer) 300 (define-key map "\C-c\C-c" #'python-shell-send-buffer)
301 (define-key map "\C-c\C-l" 'python-shell-send-file) 301 (define-key map "\C-c\C-l" #'python-shell-send-file)
302 (define-key map "\C-c\C-z" 'python-shell-switch-to-shell) 302 (define-key map "\C-c\C-z" #'python-shell-switch-to-shell)
303 ;; Some util commands 303 ;; Some util commands
304 (define-key map "\C-c\C-v" 'python-check) 304 (define-key map "\C-c\C-v" #'python-check)
305 (define-key map "\C-c\C-f" 'python-eldoc-at-point) 305 (define-key map "\C-c\C-f" #'python-eldoc-at-point)
306 (define-key map "\C-c\C-d" 'python-describe-at-point) 306 (define-key map "\C-c\C-d" #'python-describe-at-point)
307 ;; Utilities 307 ;; Utilities
308 (substitute-key-definition 'complete-symbol 'completion-at-point 308 (substitute-key-definition #'complete-symbol #'completion-at-point
309 map global-map) 309 map global-map)
310 (easy-menu-define python-menu map "Python Mode menu" 310 (easy-menu-define python-menu map "Python Mode menu"
311 '("Python" 311 '("Python"
@@ -825,7 +825,6 @@ It makes underscores and dots word constituent chars.")
825 825
826(defcustom python-indent-offset 4 826(defcustom python-indent-offset 4
827 "Default indentation offset for Python." 827 "Default indentation offset for Python."
828 :group 'python
829 :type 'integer 828 :type 'integer
830 :safe 'integerp) 829 :safe 'integerp)
831 830
@@ -835,21 +834,18 @@ It makes underscores and dots word constituent chars.")
835(defcustom python-indent-guess-indent-offset t 834(defcustom python-indent-guess-indent-offset t
836 "Non-nil tells Python mode to guess `python-indent-offset' value." 835 "Non-nil tells Python mode to guess `python-indent-offset' value."
837 :type 'boolean 836 :type 'boolean
838 :group 'python
839 :safe 'booleanp) 837 :safe 'booleanp)
840 838
841(defcustom python-indent-guess-indent-offset-verbose t 839(defcustom python-indent-guess-indent-offset-verbose t
842 "Non-nil means to emit a warning when indentation guessing fails." 840 "Non-nil means to emit a warning when indentation guessing fails."
843 :version "25.1" 841 :version "25.1"
844 :type 'boolean 842 :type 'boolean
845 :group 'python
846 :safe' booleanp) 843 :safe' booleanp)
847 844
848(defcustom python-indent-trigger-commands 845(defcustom python-indent-trigger-commands
849 '(indent-for-tab-command yas-expand yas/expand) 846 '(indent-for-tab-command yas-expand yas/expand)
850 "Commands that might trigger a `python-indent-line' call." 847 "Commands that might trigger a `python-indent-line' call."
851 :type '(repeat symbol) 848 :type '(repeat symbol))
852 :group 'python)
853 849
854(defcustom python-indent-def-block-scale 2 850(defcustom python-indent-def-block-scale 2
855 "Multiplier applied to indentation inside multi-line def blocks." 851 "Multiplier applied to indentation inside multi-line def blocks."
@@ -2031,7 +2027,6 @@ position, else returns nil."
2031(defcustom python-shell-buffer-name "Python" 2027(defcustom python-shell-buffer-name "Python"
2032 "Default buffer name for Python interpreter." 2028 "Default buffer name for Python interpreter."
2033 :type 'string 2029 :type 'string
2034 :group 'python
2035 :safe 'stringp) 2030 :safe 'stringp)
2036 2031
2037(defcustom python-shell-interpreter 2032(defcustom python-shell-interpreter
@@ -2045,19 +2040,16 @@ Some Python interpreters also require changes to
2045`python-shell-interpreter' to \"ipython3\" requires setting 2040`python-shell-interpreter' to \"ipython3\" requires setting
2046`python-shell-interpreter-args' to \"--simple-prompt\"." 2041`python-shell-interpreter-args' to \"--simple-prompt\"."
2047 :version "28.1" 2042 :version "28.1"
2048 :type 'string 2043 :type 'string)
2049 :group 'python)
2050 2044
2051(defcustom python-shell-internal-buffer-name "Python Internal" 2045(defcustom python-shell-internal-buffer-name "Python Internal"
2052 "Default buffer name for the Internal Python interpreter." 2046 "Default buffer name for the Internal Python interpreter."
2053 :type 'string 2047 :type 'string
2054 :group 'python
2055 :safe 'stringp) 2048 :safe 'stringp)
2056 2049
2057(defcustom python-shell-interpreter-args "-i" 2050(defcustom python-shell-interpreter-args "-i"
2058 "Default arguments for the Python interpreter." 2051 "Default arguments for the Python interpreter."
2059 :type 'string 2052 :type 'string)
2060 :group 'python)
2061 2053
2062(defcustom python-shell-interpreter-interactive-arg "-i" 2054(defcustom python-shell-interpreter-interactive-arg "-i"
2063 "Interpreter argument to force it to run interactively." 2055 "Interpreter argument to force it to run interactively."
@@ -2122,7 +2114,6 @@ It should not contain a caret (^) at the beginning."
2122 "Should syntax highlighting be enabled in the Python shell buffer? 2114 "Should syntax highlighting be enabled in the Python shell buffer?
2123Restart the Python shell after changing this variable for it to take effect." 2115Restart the Python shell after changing this variable for it to take effect."
2124 :type 'boolean 2116 :type 'boolean
2125 :group 'python
2126 :safe 'booleanp) 2117 :safe 'booleanp)
2127 2118
2128(defcustom python-shell-unbuffered t 2119(defcustom python-shell-unbuffered t
@@ -2130,7 +2121,6 @@ Restart the Python shell after changing this variable for it to take effect."
2130When non-nil, this may prevent delayed and missing output in the 2121When non-nil, this may prevent delayed and missing output in the
2131Python shell. See commentary for details." 2122Python shell. See commentary for details."
2132 :type 'boolean 2123 :type 'boolean
2133 :group 'python
2134 :safe 'booleanp) 2124 :safe 'booleanp)
2135 2125
2136(defcustom python-shell-process-environment nil 2126(defcustom python-shell-process-environment nil
@@ -2140,8 +2130,7 @@ When this variable is non-nil, values are exported into the
2140process environment before starting it. Any variables already 2130process environment before starting it. Any variables already
2141present in the current environment are superseded by variables 2131present in the current environment are superseded by variables
2142set here." 2132set here."
2143 :type '(repeat string) 2133 :type '(repeat string))
2144 :group 'python)
2145 2134
2146(defcustom python-shell-extra-pythonpaths nil 2135(defcustom python-shell-extra-pythonpaths nil
2147 "List of extra pythonpaths for Python shell. 2136 "List of extra pythonpaths for Python shell.
@@ -2150,8 +2139,7 @@ the PYTHONPATH before starting processes. Any values present
2150here that already exists in PYTHONPATH are moved to the beginning 2139here that already exists in PYTHONPATH are moved to the beginning
2151of the list so that they are prioritized when looking for 2140of the list so that they are prioritized when looking for
2152modules." 2141modules."
2153 :type '(repeat string) 2142 :type '(repeat string))
2154 :group 'python)
2155 2143
2156(defcustom python-shell-exec-path nil 2144(defcustom python-shell-exec-path nil
2157 "List of paths for searching executables. 2145 "List of paths for searching executables.
@@ -2159,8 +2147,7 @@ When this variable is non-nil, values added at the beginning of
2159the PATH before starting processes. Any values present here that 2147the PATH before starting processes. Any values present here that
2160already exists in PATH are moved to the beginning of the list so 2148already exists in PATH are moved to the beginning of the list so
2161that they are prioritized when looking for executables." 2149that they are prioritized when looking for executables."
2162 :type '(repeat string) 2150 :type '(repeat string))
2163 :group 'python)
2164 2151
2165(defcustom python-shell-remote-exec-path nil 2152(defcustom python-shell-remote-exec-path nil
2166 "List of paths to be ensured remotely for searching executables. 2153 "List of paths to be ensured remotely for searching executables.
@@ -2171,8 +2158,7 @@ here. Normally you won't use this variable directly unless you
2171plan to ensure a particular set of paths to all Python shell 2158plan to ensure a particular set of paths to all Python shell
2172executed through tramp connections." 2159executed through tramp connections."
2173 :version "25.1" 2160 :version "25.1"
2174 :type '(repeat string) 2161 :type '(repeat string))
2175 :group 'python)
2176 2162
2177(define-obsolete-variable-alias 2163(define-obsolete-variable-alias
2178 'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1") 2164 'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1")
@@ -2182,13 +2168,11 @@ executed through tramp connections."
2182This variable, when set to a string, makes the environment to be 2168This variable, when set to a string, makes the environment to be
2183modified such that shells are started within the specified 2169modified such that shells are started within the specified
2184virtualenv." 2170virtualenv."
2185 :type '(choice (const nil) directory) 2171 :type '(choice (const nil) directory))
2186 :group 'python)
2187 2172
2188(defcustom python-shell-setup-codes nil 2173(defcustom python-shell-setup-codes nil
2189 "List of code run by `python-shell-send-setup-code'." 2174 "List of code run by `python-shell-send-setup-code'."
2190 :type '(repeat symbol) 2175 :type '(repeat symbol))
2191 :group 'python)
2192 2176
2193(defcustom python-shell-compilation-regexp-alist 2177(defcustom python-shell-compilation-regexp-alist
2194 `((,(rx line-start (1+ (any " \t")) "File \"" 2178 `((,(rx line-start (1+ (any " \t")) "File \""
@@ -2202,8 +2186,7 @@ virtualenv."
2202 "(" (group (1+ digit)) ")" (1+ (not (any "("))) "()") 2186 "(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
2203 1 2)) 2187 1 2))
2204 "`compilation-error-regexp-alist' for inferior Python." 2188 "`compilation-error-regexp-alist' for inferior Python."
2205 :type '(alist regexp) 2189 :type '(alist regexp))
2206 :group 'python)
2207 2190
2208(defvar python-shell-output-filter-in-progress nil) 2191(defvar python-shell-output-filter-in-progress nil)
2209(defvar python-shell-output-filter-buffer nil) 2192(defvar python-shell-output-filter-buffer nil)
@@ -2221,33 +2204,33 @@ virtualenv."
2221 (or (getenv "PYTHONPATH") "") path-separator 'omit))) 2204 (or (getenv "PYTHONPATH") "") path-separator 'omit)))
2222 (python-shell--add-to-path-with-priority 2205 (python-shell--add-to-path-with-priority
2223 pythonpath python-shell-extra-pythonpaths) 2206 pythonpath python-shell-extra-pythonpaths)
2224 (mapconcat 'identity pythonpath path-separator))) 2207 (mapconcat #'identity pythonpath path-separator)))
2225 2208
2226(defun python-shell-calculate-process-environment () 2209(defun python-shell-calculate-process-environment ()
2227 "Calculate `process-environment' or `tramp-remote-process-environment'. 2210 (declare (obsolete python-shell--calculate-process-environment "29.1"))
2211 (let* ((remote-p (file-remote-p default-directory)))
2212 (append (python-shell--calculate-process-environment)
2213 (if remote-p
2214 tramp-remote-process-environment
2215 process-environment))))
2216
2217(defun python-shell--calculate-process-environment ()
2218 "Return a list of entries to add to the `process-environment'.
2228Prepends `python-shell-process-environment', sets extra 2219Prepends `python-shell-process-environment', sets extra
2229pythonpaths from `python-shell-extra-pythonpaths' and sets a few 2220pythonpaths from `python-shell-extra-pythonpaths' and sets a few
2230virtualenv related vars. If `default-directory' points to a 2221virtualenv related vars."
2231remote host, the returned value is intended for 2222 (let* ((virtualenv (when python-shell-virtualenv-root
2232`tramp-remote-process-environment'." 2223 (directory-file-name python-shell-virtualenv-root)))
2233 (let* ((remote-p (file-remote-p default-directory)) 2224 (res python-shell-process-environment))
2234 (process-environment (if remote-p
2235 tramp-remote-process-environment
2236 process-environment))
2237 (virtualenv (when python-shell-virtualenv-root
2238 (directory-file-name python-shell-virtualenv-root))))
2239 (dolist (env python-shell-process-environment)
2240 (pcase-let ((`(,key ,value) (split-string env "=")))
2241 (setenv key value)))
2242 (when python-shell-unbuffered 2225 (when python-shell-unbuffered
2243 (setenv "PYTHONUNBUFFERED" "1")) 2226 (push "PYTHONUNBUFFERED=1" res))
2244 (when python-shell-extra-pythonpaths 2227 (when python-shell-extra-pythonpaths
2245 (setenv "PYTHONPATH" (python-shell-calculate-pythonpath))) 2228 (push (concat "PYTHONPATH=" (python-shell-calculate-pythonpath)) res))
2246 (if (not virtualenv) 2229 (if (not virtualenv)
2247 process-environment 2230 nil
2248 (setenv "PYTHONHOME" nil) 2231 (push "PYTHONHOME" res)
2249 (setenv "VIRTUAL_ENV" virtualenv)) 2232 (push (concat "VIRTUAL_ENV=" virtualenv) res))
2250 process-environment)) 2233 res))
2251 2234
2252(defun python-shell-calculate-exec-path () 2235(defun python-shell-calculate-exec-path ()
2253 "Calculate `exec-path'. 2236 "Calculate `exec-path'.
@@ -2275,14 +2258,26 @@ of `exec-path'."
2275 2258
2276(defun python-shell-tramp-refresh-remote-path (vec paths) 2259(defun python-shell-tramp-refresh-remote-path (vec paths)
2277 "Update VEC's remote-path giving PATHS priority." 2260 "Update VEC's remote-path giving PATHS priority."
2261 (cl-assert (featurep 'tramp))
2262 (declare-function tramp-set-remote-path "tramp-sh")
2263 (declare-function tramp-set-connection-property "tramp-cache")
2264 (declare-function tramp-get-connection-property "tramp-cache")
2278 (let ((remote-path (tramp-get-connection-property vec "remote-path" nil))) 2265 (let ((remote-path (tramp-get-connection-property vec "remote-path" nil)))
2279 (when remote-path 2266 (when remote-path
2267 ;; FIXME: This part of the Tramp code still knows about Python!
2280 (python-shell--add-to-path-with-priority remote-path paths) 2268 (python-shell--add-to-path-with-priority remote-path paths)
2281 (tramp-set-connection-property vec "remote-path" remote-path) 2269 (tramp-set-connection-property vec "remote-path" remote-path)
2282 (tramp-set-remote-path vec)))) 2270 (tramp-set-remote-path vec))))
2283 2271
2272
2284(defun python-shell-tramp-refresh-process-environment (vec env) 2273(defun python-shell-tramp-refresh-process-environment (vec env)
2285 "Update VEC's process environment with ENV." 2274 "Update VEC's process environment with ENV."
2275 (cl-assert (featurep 'tramp))
2276 (defvar tramp-end-of-heredoc)
2277 (defvar tramp-end-of-output)
2278 ;; Do we even know that `tramp-sh' is loaded at this point?
2279 ;; What about files accessed via FTP, sudo, ...?
2280 (declare-function tramp-send-command "tramp-sh")
2286 ;; Stolen from `tramp-open-connection-setup-interactive-shell'. 2281 ;; Stolen from `tramp-open-connection-setup-interactive-shell'.
2287 (let ((env (append (when (fboundp 'tramp-get-remote-locale) 2282 (let ((env (append (when (fboundp 'tramp-get-remote-locale)
2288 ;; Emacs<24.4 compat. 2283 ;; Emacs<24.4 compat.
@@ -2295,7 +2290,7 @@ of `exec-path'."
2295 unset vars item) 2290 unset vars item)
2296 (while env 2291 (while env
2297 (setq item (split-string (car env) "=" 'omit)) 2292 (setq item (split-string (car env) "=" 'omit))
2298 (setcdr item (mapconcat 'identity (cdr item) "=")) 2293 (setcdr item (mapconcat #'identity (cdr item) "="))
2299 (if (and (stringp (cdr item)) (not (string-equal (cdr item) ""))) 2294 (if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
2300 (push (format "%s %s" (car item) (cdr item)) vars) 2295 (push (format "%s %s" (car item) (cdr item)) vars)
2301 (push (car item) unset)) 2296 (push (car item) unset))
@@ -2305,12 +2300,12 @@ of `exec-path'."
2305 vec 2300 vec
2306 (format "while read var val; do export $var=$val; done <<'%s'\n%s\n%s" 2301 (format "while read var val; do export $var=$val; done <<'%s'\n%s\n%s"
2307 tramp-end-of-heredoc 2302 tramp-end-of-heredoc
2308 (mapconcat 'identity vars "\n") 2303 (mapconcat #'identity vars "\n")
2309 tramp-end-of-heredoc) 2304 tramp-end-of-heredoc)
2310 t)) 2305 t))
2311 (when unset 2306 (when unset
2312 (tramp-send-command 2307 (tramp-send-command
2313 vec (format "unset %s" (mapconcat 'identity unset " ")) t)))) 2308 vec (format "unset %s" (mapconcat #'identity unset " ")) t))))
2314 2309
2315(defmacro python-shell-with-environment (&rest body) 2310(defmacro python-shell-with-environment (&rest body)
2316 "Modify shell environment during execution of BODY. 2311 "Modify shell environment during execution of BODY.
@@ -2319,41 +2314,49 @@ execution of body. If `default-directory' points to a remote
2319machine then modifies `tramp-remote-process-environment' and 2314machine then modifies `tramp-remote-process-environment' and
2320`python-shell-remote-exec-path' instead." 2315`python-shell-remote-exec-path' instead."
2321 (declare (indent 0) (debug (body))) 2316 (declare (indent 0) (debug (body)))
2322 (let ((vec (make-symbol "vec"))) 2317 `(python-shell--with-environment
2323 `(progn 2318 (python-shell--calculate-process-environment)
2324 (let* ((,vec 2319 (lambda () ,@body)))
2325 (when (file-remote-p default-directory) 2320
2326 (ignore-errors 2321(defun python-shell--with-environment (extraenv bodyfun)
2327 (tramp-dissect-file-name default-directory 'noexpand)))) 2322 ;; FIXME: This is where the generic code delegates to Tramp.
2328 (process-environment 2323 (let* ((vec
2329 (if ,vec 2324 (and (file-remote-p default-directory)
2330 process-environment 2325 (fboundp 'tramp-dissect-file-name)
2331 (python-shell-calculate-process-environment))) 2326 (ignore-errors
2332 (exec-path 2327 (tramp-dissect-file-name default-directory 'noexpand)))))
2333 (if ,vec 2328 (if vec
2334 exec-path 2329 (python-shell--tramp-with-environment vec extraenv bodyfun)
2335 (python-shell-calculate-exec-path))) 2330 (let ((process-environment
2336 (tramp-remote-process-environment 2331 (append extraenv process-environment))
2337 (if ,vec 2332 (exec-path
2338 (python-shell-calculate-process-environment) 2333 ;; FIXME: This is still Python-specific.
2339 tramp-remote-process-environment))) 2334 (python-shell-calculate-exec-path)))
2340 (when (tramp-get-connection-process ,vec) 2335 (funcall bodyfun)))))
2341 ;; For already existing connections, the new exec path must 2336
2342 ;; be re-set, otherwise it won't take effect. One example 2337(defun python-shell--tramp-with-environment (vec extraenv bodyfun)
2343 ;; of such case is when remote dir-locals are read and 2338 (defvar tramp-remote-process-environment)
2344 ;; *then* subprocesses are triggered within the same 2339 (declare-function tramp-get-connection-process "tramp" (vec))
2345 ;; connection. 2340 (let* ((tramp-remote-process-environment
2346 (python-shell-tramp-refresh-remote-path 2341 (append extraenv tramp-remote-process-environment)))
2347 ,vec (python-shell-calculate-exec-path)) 2342 (when (tramp-get-connection-process vec)
2348 ;; The `tramp-remote-process-environment' variable is only 2343 ;; For already existing connections, the new exec path must
2349 ;; effective when the started process is an interactive 2344 ;; be re-set, otherwise it won't take effect. One example
2350 ;; shell, otherwise (like in the case of processes started 2345 ;; of such case is when remote dir-locals are read and
2351 ;; with `process-file') the environment is not changed. 2346 ;; *then* subprocesses are triggered within the same
2352 ;; This makes environment modifications effective 2347 ;; connection.
2353 ;; unconditionally. 2348 (python-shell-tramp-refresh-remote-path
2354 (python-shell-tramp-refresh-process-environment 2349 ;; FIXME: This is still Python-specific.
2355 ,vec tramp-remote-process-environment)) 2350 vec (python-shell-calculate-exec-path))
2356 ,(macroexp-progn body))))) 2351 ;; The `tramp-remote-process-environment' variable is only
2352 ;; effective when the started process is an interactive
2353 ;; shell, otherwise (like in the case of processes started
2354 ;; with `process-file') the environment is not changed.
2355 ;; This makes environment modifications effective
2356 ;; unconditionally.
2357 (python-shell-tramp-refresh-process-environment
2358 vec tramp-remote-process-environment))
2359 (funcall bodyfun)))
2357 2360
2358(defvar python-shell--prompt-calculated-input-regexp nil 2361(defvar python-shell--prompt-calculated-input-regexp nil
2359 "Calculated input prompt regexp for inferior python shell. 2362 "Calculated input prompt regexp for inferior python shell.
@@ -2636,7 +2639,7 @@ banner and the initial prompt are received separately."
2636 2639
2637(define-obsolete-function-alias 2640(define-obsolete-function-alias
2638 'python-comint-output-filter-function 2641 'python-comint-output-filter-function
2639 'ansi-color-filter-apply 2642 #'ansi-color-filter-apply
2640 "25.1") 2643 "25.1")
2641 2644
2642(defun python-comint-postoutput-scroll-to-bottom (output) 2645(defun python-comint-postoutput-scroll-to-bottom (output)
@@ -2821,8 +2824,7 @@ current process to not hang while waiting. This is useful to
2821safely attach setup code for long-running processes that 2824safely attach setup code for long-running processes that
2822eventually provide a shell." 2825eventually provide a shell."
2823 :version "25.1" 2826 :version "25.1"
2824 :type 'hook 2827 :type 'hook)
2825 :group 'python)
2826 2828
2827(defconst python-shell-eval-setup-code 2829(defconst python-shell-eval-setup-code
2828 "\ 2830 "\
@@ -2956,7 +2958,7 @@ variable.
2956 (add-hook 'completion-at-point-functions 2958 (add-hook 'completion-at-point-functions
2957 #'python-shell-completion-at-point nil 'local) 2959 #'python-shell-completion-at-point nil 'local)
2958 (define-key inferior-python-mode-map "\t" 2960 (define-key inferior-python-mode-map "\t"
2959 'python-shell-completion-complete-or-indent) 2961 #'python-shell-completion-complete-or-indent)
2960 (make-local-variable 'python-shell-internal-last-output) 2962 (make-local-variable 'python-shell-internal-last-output)
2961 (when python-shell-font-lock-enable 2963 (when python-shell-font-lock-enable
2962 (python-shell-font-lock-turn-on)) 2964 (python-shell-font-lock-turn-on))
@@ -2982,7 +2984,8 @@ killed."
2982 (let* ((cmdlist (split-string-and-unquote cmd)) 2984 (let* ((cmdlist (split-string-and-unquote cmd))
2983 (interpreter (car cmdlist)) 2985 (interpreter (car cmdlist))
2984 (args (cdr cmdlist)) 2986 (args (cdr cmdlist))
2985 (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name 2987 (buffer (apply #'make-comint-in-buffer proc-name
2988 proc-buffer-name
2986 interpreter nil args)) 2989 interpreter nil args))
2987 (python-shell--parent-buffer (current-buffer)) 2990 (python-shell--parent-buffer (current-buffer))
2988 (process (get-buffer-process buffer)) 2991 (process (get-buffer-process buffer))
@@ -3131,7 +3134,7 @@ there for compatibility with CEDET.")
3131 (run-python-internal)))) 3134 (run-python-internal))))
3132 3135
3133(define-obsolete-function-alias 3136(define-obsolete-function-alias
3134 'python-proc 'python-shell-internal-get-or-create-process "24.3") 3137 'python-proc #'python-shell-internal-get-or-create-process "24.3")
3135 3138
3136(defun python-shell--save-temp-file (string) 3139(defun python-shell--save-temp-file (string)
3137 (let* ((temporary-file-directory 3140 (let* ((temporary-file-directory
@@ -3250,10 +3253,10 @@ Returns the output. See `python-shell-send-string-no-output'."
3250 (python-shell-internal-get-or-create-process)))) 3253 (python-shell-internal-get-or-create-process))))
3251 3254
3252(define-obsolete-function-alias 3255(define-obsolete-function-alias
3253 'python-send-receive 'python-shell-internal-send-string "24.3") 3256 'python-send-receive #'python-shell-internal-send-string "24.3")
3254 3257
3255(define-obsolete-function-alias 3258(define-obsolete-function-alias
3256 'python-send-string 'python-shell-internal-send-string "24.3") 3259 'python-send-string #'python-shell-internal-send-string "24.3")
3257 3260
3258(defun python-shell-buffer-substring (start end &optional nomain no-cookie) 3261(defun python-shell-buffer-substring (start end &optional nomain no-cookie)
3259 "Send buffer substring from START to END formatted for shell. 3262 "Send buffer substring from START to END formatted for shell.
@@ -3549,8 +3552,7 @@ def __PYTHON_EL_get_completions(text):
3549 completer.print_mode = True 3552 completer.print_mode = True
3550 return completions" 3553 return completions"
3551 "Code used to setup completion in inferior Python processes." 3554 "Code used to setup completion in inferior Python processes."
3552 :type 'string 3555 :type 'string)
3553 :group 'python)
3554 3556
3555(define-obsolete-variable-alias 3557(define-obsolete-variable-alias
3556 'python-shell-completion-module-string-code 3558 'python-shell-completion-module-string-code
@@ -3823,7 +3825,8 @@ With argument MSG show activation/deactivation message."
3823 ;; in use based on its args and uses `apply-partially' 3825 ;; in use based on its args and uses `apply-partially'
3824 ;; to make it up for the 3 args case. 3826 ;; to make it up for the 3 args case.
3825 (if (= (length 3827 (if (= (length
3826 (help-function-arglist 'comint-redirect-filter)) 3) 3828 (help-function-arglist 'comint-redirect-filter))
3829 3)
3827 (set-process-filter 3830 (set-process-filter
3828 process (apply-partially 3831 process (apply-partially
3829 #'comint-redirect-filter original-filter-fn)) 3832 #'comint-redirect-filter original-filter-fn))
@@ -3932,7 +3935,7 @@ using that one instead of current buffer's process."
3932 3935
3933(define-obsolete-function-alias 3936(define-obsolete-function-alias
3934 'python-shell-completion-complete-at-point 3937 'python-shell-completion-complete-at-point
3935 'python-shell-completion-at-point 3938 #'python-shell-completion-at-point
3936 "25.1") 3939 "25.1")
3937 3940
3938(defun python-shell-completion-complete-or-indent () 3941(defun python-shell-completion-complete-or-indent ()
@@ -3961,7 +3964,6 @@ considered over. The overlay arrow will be removed from the currently tracked
3961buffer. Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all 3964buffer. Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all
3962files opened by pdbtracking will be killed." 3965files opened by pdbtracking will be killed."
3963 :type 'boolean 3966 :type 'boolean
3964 :group 'python
3965 :safe 'booleanp) 3967 :safe 'booleanp)
3966 3968
3967(defcustom python-pdbtrack-stacktrace-info-regexp 3969(defcustom python-pdbtrack-stacktrace-info-regexp
@@ -4170,7 +4172,7 @@ inferior Python process is updated properly."
4170 4172
4171(define-obsolete-function-alias 4173(define-obsolete-function-alias
4172 'python-completion-complete-at-point 4174 'python-completion-complete-at-point
4173 'python-completion-at-point 4175 #'python-completion-at-point
4174 "25.1") 4176 "25.1")
4175 4177
4176 4178
@@ -4180,29 +4182,25 @@ inferior Python process is updated properly."
4180 "Function to fill comments. 4182 "Function to fill comments.
4181This is the function used by `python-fill-paragraph' to 4183This is the function used by `python-fill-paragraph' to
4182fill comments." 4184fill comments."
4183 :type 'symbol 4185 :type 'symbol)
4184 :group 'python)
4185 4186
4186(defcustom python-fill-string-function 'python-fill-string 4187(defcustom python-fill-string-function 'python-fill-string
4187 "Function to fill strings. 4188 "Function to fill strings.
4188This is the function used by `python-fill-paragraph' to 4189This is the function used by `python-fill-paragraph' to
4189fill strings." 4190fill strings."
4190 :type 'symbol 4191 :type 'symbol)
4191 :group 'python)
4192 4192
4193(defcustom python-fill-decorator-function 'python-fill-decorator 4193(defcustom python-fill-decorator-function 'python-fill-decorator
4194 "Function to fill decorators. 4194 "Function to fill decorators.
4195This is the function used by `python-fill-paragraph' to 4195This is the function used by `python-fill-paragraph' to
4196fill decorators." 4196fill decorators."
4197 :type 'symbol 4197 :type 'symbol)
4198 :group 'python)
4199 4198
4200(defcustom python-fill-paren-function 'python-fill-paren 4199(defcustom python-fill-paren-function 'python-fill-paren
4201 "Function to fill parens. 4200 "Function to fill parens.
4202This is the function used by `python-fill-paragraph' to 4201This is the function used by `python-fill-paragraph' to
4203fill parens." 4202fill parens."
4204 :type 'symbol 4203 :type 'symbol)
4205 :group 'python)
4206 4204
4207(defcustom python-fill-docstring-style 'pep-257 4205(defcustom python-fill-docstring-style 'pep-257
4208 "Style used to fill docstrings. 4206 "Style used to fill docstrings.
@@ -4272,7 +4270,6 @@ value may result in one of the following docstring styles:
4272 (const :tag "PEP-257 with 2 newlines at end of string." pep-257) 4270 (const :tag "PEP-257 with 2 newlines at end of string." pep-257)
4273 (const :tag "PEP-257 with 1 newline at end of string." pep-257-nn) 4271 (const :tag "PEP-257 with 1 newline at end of string." pep-257-nn)
4274 (const :tag "Symmetric style." symmetric)) 4272 (const :tag "Symmetric style." symmetric))
4275 :group 'python
4276 :safe (lambda (val) 4273 :safe (lambda (val)
4277 (memq val '(django onetwo pep-257 pep-257-nn symmetric nil)))) 4274 (memq val '(django onetwo pep-257 pep-257-nn symmetric nil))))
4278 4275
@@ -4431,7 +4428,6 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
4431This happens when pressing \"if<SPACE>\", for example, to prompt for 4428This happens when pressing \"if<SPACE>\", for example, to prompt for
4432the if condition." 4429the if condition."
4433 :type 'boolean 4430 :type 'boolean
4434 :group 'python
4435 :safe 'booleanp) 4431 :safe 'booleanp)
4436 4432
4437(defvar python-skeleton-available '() 4433(defvar python-skeleton-available '()
@@ -4556,7 +4552,7 @@ The skeleton will be bound to python-skeleton-NAME."
4556 4552
4557(defun python-skeleton-add-menu-items () 4553(defun python-skeleton-add-menu-items ()
4558 "Add menu items to Python->Skeletons menu." 4554 "Add menu items to Python->Skeletons menu."
4559 (let ((skeletons (sort python-skeleton-available 'string<))) 4555 (let ((skeletons (sort python-skeleton-available #'string<)))
4560 (dolist (skeleton skeletons) 4556 (dolist (skeleton skeletons)
4561 (easy-menu-add-item 4557 (easy-menu-add-item
4562 nil '("Python" "Skeletons") 4558 nil '("Python" "Skeletons")
@@ -4586,8 +4582,7 @@ def __FFAP_get_module_path(objstr):
4586 except: 4582 except:
4587 return ''" 4583 return ''"
4588 "Python code to get a module path." 4584 "Python code to get a module path."
4589 :type 'string 4585 :type 'string)
4590 :group 'python)
4591 4586
4592(defun python-ffap-module-path (module) 4587(defun python-ffap-module-path (module)
4593 "Function for `ffap-alist' to return path for MODULE." 4588 "Function for `ffap-alist' to return path for MODULE."
@@ -4615,14 +4610,12 @@ def __FFAP_get_module_path(objstr):
4615 (executable-find "epylint") 4610 (executable-find "epylint")
4616 "install pyflakes, pylint or something else") 4611 "install pyflakes, pylint or something else")
4617 "Command used to check a Python file." 4612 "Command used to check a Python file."
4618 :type 'string 4613 :type 'string)
4619 :group 'python)
4620 4614
4621(defcustom python-check-buffer-name 4615(defcustom python-check-buffer-name
4622 "*Python check: %s*" 4616 "*Python check: %s*"
4623 "Buffer name used for check commands." 4617 "Buffer name used for check commands."
4624 :type 'string 4618 :type 'string)
4625 :group 'python)
4626 4619
4627(defvar python-check-custom-command nil 4620(defvar python-check-custom-command nil
4628 "Internal use.") 4621 "Internal use.")
@@ -4689,8 +4682,7 @@ See `python-check-command' for the default."
4689 doc = '' 4682 doc = ''
4690 return doc" 4683 return doc"
4691 "Python code to setup documentation retrieval." 4684 "Python code to setup documentation retrieval."
4692 :type 'string 4685 :type 'string)
4693 :group 'python)
4694 4686
4695(defun python-eldoc--get-symbol-at-point () 4687(defun python-eldoc--get-symbol-at-point ()
4696 "Get the current symbol for eldoc. 4688 "Get the current symbol for eldoc.
@@ -4737,14 +4729,13 @@ Set to nil by `python-eldoc-function' if
4737 4729
4738(defcustom python-eldoc-function-timeout 1 4730(defcustom python-eldoc-function-timeout 1
4739 "Timeout for `python-eldoc-function' in seconds." 4731 "Timeout for `python-eldoc-function' in seconds."
4740 :group 'python
4741 :type 'integer 4732 :type 'integer
4742 :version "25.1") 4733 :version "25.1")
4743 4734
4744(defcustom python-eldoc-function-timeout-permanent t 4735(defcustom python-eldoc-function-timeout-permanent t
4745 "Non-nil means that when `python-eldoc-function' times out 4736 "If non-nil, a timeout in Python-Eldoc will disable it permanently.
4746`python-eldoc-get-doc' will be set to nil." 4737Python-Eldoc can be re-enabled manually by setting `python-eldoc-get-doc'
4747 :group 'python 4738back to t in the affected buffer."
4748 :type 'boolean 4739 :type 'boolean
4749 :version "25.1") 4740 :version "25.1")
4750 4741
@@ -4936,7 +4927,7 @@ To this:
4936 (\"decorator.wrapped_f\" . 393))" 4927 (\"decorator.wrapped_f\" . 393))"
4937 ;; Inspired by imenu--flatten-index-alist removed in revno 21853. 4928 ;; Inspired by imenu--flatten-index-alist removed in revno 21853.
4938 (apply 4929 (apply
4939 'nconc 4930 #'nconc
4940 (mapcar 4931 (mapcar
4941 (lambda (item) 4932 (lambda (item)
4942 (let ((name (if prefix 4933 (let ((name (if prefix
@@ -5019,7 +5010,7 @@ since it returns nil if point is not inside a defun."
5019 (and (= (current-indentation) 0) (throw 'exit t)))) 5010 (and (= (current-indentation) 0) (throw 'exit t))))
5020 (and names 5011 (and names
5021 (concat (and type (format "%s " type)) 5012 (concat (and type (format "%s " type))
5022 (mapconcat 'identity names "."))))))) 5013 (mapconcat #'identity names ".")))))))
5023 5014
5024(defun python-info-current-symbol (&optional replace-self) 5015(defun python-info-current-symbol (&optional replace-self)
5025 "Return current symbol using dotty syntax. 5016 "Return current symbol using dotty syntax.
@@ -5040,9 +5031,10 @@ parent defun name."
5040 (replace-regexp-in-string 5031 (replace-regexp-in-string
5041 (python-rx line-start word-start "self" word-end ?.) 5032 (python-rx line-start word-start "self" word-end ?.)
5042 (concat 5033 (concat
5043 (mapconcat 'identity 5034 (mapconcat #'identity
5044 (butlast (split-string current-defun "\\.")) 5035 (butlast (split-string current-defun "\\."))
5045 ".") ".") 5036 ".")
5037 ".")
5046 name))))))) 5038 name)))))))
5047 5039
5048(defun python-info-statement-starts-block-p () 5040(defun python-info-statement-starts-block-p ()
@@ -5084,7 +5076,7 @@ parent defun name."
5084 5076
5085(define-obsolete-function-alias 5077(define-obsolete-function-alias
5086 'python-info-closing-block 5078 'python-info-closing-block
5087 'python-info-dedenter-opening-block-position "24.4") 5079 #'python-info-dedenter-opening-block-position "24.4")
5088 5080
5089(defun python-info-dedenter-opening-block-position () 5081(defun python-info-dedenter-opening-block-position ()
5090 "Return the point of the closest block the current line closes. 5082 "Return the point of the closest block the current line closes.
@@ -5129,7 +5121,8 @@ likely an invalid python file."
5129 (let ((indentation (current-indentation))) 5121 (let ((indentation (current-indentation)))
5130 (when (and (not (memq indentation collected-indentations)) 5122 (when (and (not (memq indentation collected-indentations))
5131 (or (not collected-indentations) 5123 (or (not collected-indentations)
5132 (< indentation (apply #'min collected-indentations))) 5124 (< indentation
5125 (apply #'min collected-indentations)))
5133 ;; There must be no line with indentation 5126 ;; There must be no line with indentation
5134 ;; smaller than `indentation' (except for 5127 ;; smaller than `indentation' (except for
5135 ;; blank lines) between the found opening 5128 ;; blank lines) between the found opening
@@ -5157,7 +5150,7 @@ likely an invalid python file."
5157 5150
5158(define-obsolete-function-alias 5151(define-obsolete-function-alias
5159 'python-info-closing-block-message 5152 'python-info-closing-block-message
5160 'python-info-dedenter-opening-block-message "24.4") 5153 #'python-info-dedenter-opening-block-message "24.4")
5161 5154
5162(defun python-info-dedenter-opening-block-message () 5155(defun python-info-dedenter-opening-block-message ()
5163 "Message the first line of the block the current statement closes." 5156 "Message the first line of the block the current statement closes."
@@ -5459,10 +5452,12 @@ allowed files."
5459 (let ((dir-name (file-name-as-directory dir))) 5452 (let ((dir-name (file-name-as-directory dir)))
5460 (apply #'nconc 5453 (apply #'nconc
5461 (mapcar (lambda (file-name) 5454 (mapcar (lambda (file-name)
5462 (let ((full-file-name (expand-file-name file-name dir-name))) 5455 (let ((full-file-name
5456 (expand-file-name file-name dir-name)))
5463 (when (and 5457 (when (and
5464 (not (member file-name '("." ".."))) 5458 (not (member file-name '("." "..")))
5465 (funcall (or predicate #'identity) full-file-name)) 5459 (funcall (or predicate #'identity)
5460 full-file-name))
5466 (list full-file-name)))) 5461 (list full-file-name))))
5467 (directory-files dir-name))))) 5462 (directory-files dir-name)))))
5468 5463
@@ -5530,7 +5525,6 @@ required arguments. Once launched it will receive the Python source to be
5530checked as its standard input. 5525checked as its standard input.
5531To use `flake8' you would set this to (\"flake8\" \"-\")." 5526To use `flake8' you would set this to (\"flake8\" \"-\")."
5532 :version "26.1" 5527 :version "26.1"
5533 :group 'python-flymake
5534 :type '(repeat string)) 5528 :type '(repeat string))
5535 5529
5536;; The default regexp accommodates for older pyflakes, which did not 5530;; The default regexp accommodates for older pyflakes, which did not
@@ -5552,7 +5546,6 @@ If COLUMN or TYPE are nil or that index didn't match, that
5552information is not present on the matched line and a default will 5546information is not present on the matched line and a default will
5553be used." 5547be used."
5554 :version "26.1" 5548 :version "26.1"
5555 :group 'python-flymake
5556 :type '(list regexp 5549 :type '(list regexp
5557 (integer :tag "Line's index") 5550 (integer :tag "Line's index")
5558 (choice 5551 (choice
@@ -5577,7 +5570,6 @@ configuration could be:
5577 5570
5578By default messages are considered errors." 5571By default messages are considered errors."
5579 :version "26.1" 5572 :version "26.1"
5580 :group 'python-flymake
5581 :type '(alist :key-type (regexp) 5573 :type '(alist :key-type (regexp)
5582 :value-type (symbol))) 5574 :value-type (symbol)))
5583 5575