emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d340dc0a25: python.el: Try and better split the Tramp code


From: Stefan Monnier
Subject: master d340dc0a25: python.el: Try and better split the Tramp code
Date: Fri, 4 Feb 2022 13:35:41 -0500 (EST)

branch: master
commit d340dc0a256db979c617bd5ee06dafa5a52791f5
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    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.
---
 lisp/progmodes/python.el            | 322 ++++++++++++++++++------------------
 test/lisp/progmodes/python-tests.el |  76 ++++++---
 2 files changed, 207 insertions(+), 191 deletions(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 5889f2ab67..ba8e3e811d 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -92,7 +92,7 @@
 ;; Operating Systems' pipe buffering (e.g. CPython 3.3.4 in Windows 7.
 ;; See URL `https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304').  To
 ;; avoid this, the `python-shell-unbuffered' defaults to non-nil and
-;; controls whether `python-shell-calculate-process-environment'
+;; controls whether `python-shell--calculate-process-environment'
 ;; should set the "PYTHONUNBUFFERED" environment variable on startup:
 ;; See URL `https://docs.python.org/3/using/cmdline.html#cmdoption-u'.
 
@@ -149,7 +149,7 @@
 ;; (setq python-shell-process-environment
 ;;       (list
 ;;        (format "PATH=%s" (mapconcat
-;;                           'identity
+;;                           #'identity
 ;;                           (reverse
 ;;                            (cons (getenv "PATH")
 ;;                                  '("/path/to/env/bin/")))
@@ -245,7 +245,7 @@
 (require 'ansi-color)
 (require 'cl-lib)
 (require 'comint)
-(require 'tramp-sh)
+(eval-when-compile (require 'subr-x))   ;For `string-empty-p'.
 
 ;; Avoid compiler warnings
 (defvar view-return-to-alist)
@@ -273,39 +273,39 @@
 (defvar python-mode-map
   (let ((map (make-sparse-keymap)))
     ;; Movement
-    (define-key map [remap backward-sentence] 'python-nav-backward-block)
-    (define-key map [remap forward-sentence] 'python-nav-forward-block)
-    (define-key map [remap backward-up-list] 'python-nav-backward-up-list)
-    (define-key map [remap mark-defun] 'python-mark-defun)
-    (define-key map "\C-c\C-j" 'imenu)
+    (define-key map [remap backward-sentence] #'python-nav-backward-block)
+    (define-key map [remap forward-sentence] #'python-nav-forward-block)
+    (define-key map [remap backward-up-list] #'python-nav-backward-up-list)
+    (define-key map [remap mark-defun] #'python-mark-defun)
+    (define-key map "\C-c\C-j" #'imenu)
     ;; Indent specific
-    (define-key map "\177" 'python-indent-dedent-line-backspace)
-    (define-key map (kbd "<backtab>") 'python-indent-dedent-line)
-    (define-key map "\C-c<" 'python-indent-shift-left)
-    (define-key map "\C-c>" 'python-indent-shift-right)
+    (define-key map "\177" #'python-indent-dedent-line-backspace)
+    (define-key map (kbd "<backtab>") #'python-indent-dedent-line)
+    (define-key map "\C-c<" #'python-indent-shift-left)
+    (define-key map "\C-c>" #'python-indent-shift-right)
     ;; Skeletons
-    (define-key map "\C-c\C-tc" 'python-skeleton-class)
-    (define-key map "\C-c\C-td" 'python-skeleton-def)
-    (define-key map "\C-c\C-tf" 'python-skeleton-for)
-    (define-key map "\C-c\C-ti" 'python-skeleton-if)
-    (define-key map "\C-c\C-tm" 'python-skeleton-import)
-    (define-key map "\C-c\C-tt" 'python-skeleton-try)
-    (define-key map "\C-c\C-tw" 'python-skeleton-while)
+    (define-key map "\C-c\C-tc" #'python-skeleton-class)
+    (define-key map "\C-c\C-td" #'python-skeleton-def)
+    (define-key map "\C-c\C-tf" #'python-skeleton-for)
+    (define-key map "\C-c\C-ti" #'python-skeleton-if)
+    (define-key map "\C-c\C-tm" #'python-skeleton-import)
+    (define-key map "\C-c\C-tt" #'python-skeleton-try)
+    (define-key map "\C-c\C-tw" #'python-skeleton-while)
     ;; Shell interaction
-    (define-key map "\C-c\C-p" 'run-python)
-    (define-key map "\C-c\C-s" 'python-shell-send-string)
-    (define-key map "\C-c\C-e" 'python-shell-send-statement)
-    (define-key map "\C-c\C-r" 'python-shell-send-region)
-    (define-key map "\C-\M-x" 'python-shell-send-defun)
-    (define-key map "\C-c\C-c" 'python-shell-send-buffer)
-    (define-key map "\C-c\C-l" 'python-shell-send-file)
-    (define-key map "\C-c\C-z" 'python-shell-switch-to-shell)
+    (define-key map "\C-c\C-p" #'run-python)
+    (define-key map "\C-c\C-s" #'python-shell-send-string)
+    (define-key map "\C-c\C-e" #'python-shell-send-statement)
+    (define-key map "\C-c\C-r" #'python-shell-send-region)
+    (define-key map "\C-\M-x"  #'python-shell-send-defun)
+    (define-key map "\C-c\C-c" #'python-shell-send-buffer)
+    (define-key map "\C-c\C-l" #'python-shell-send-file)
+    (define-key map "\C-c\C-z" #'python-shell-switch-to-shell)
     ;; Some util commands
-    (define-key map "\C-c\C-v" 'python-check)
-    (define-key map "\C-c\C-f" 'python-eldoc-at-point)
-    (define-key map "\C-c\C-d" 'python-describe-at-point)
+    (define-key map "\C-c\C-v" #'python-check)
+    (define-key map "\C-c\C-f" #'python-eldoc-at-point)
+    (define-key map "\C-c\C-d" #'python-describe-at-point)
     ;; Utilities
-    (substitute-key-definition 'complete-symbol 'completion-at-point
+    (substitute-key-definition #'complete-symbol #'completion-at-point
                                map global-map)
     (easy-menu-define python-menu map "Python Mode menu"
       '("Python"
@@ -825,7 +825,6 @@ It makes underscores and dots word constituent chars.")
 
 (defcustom python-indent-offset 4
   "Default indentation offset for Python."
-  :group 'python
   :type 'integer
   :safe 'integerp)
 
@@ -835,21 +834,18 @@ It makes underscores and dots word constituent chars.")
 (defcustom python-indent-guess-indent-offset t
   "Non-nil tells Python mode to guess `python-indent-offset' value."
   :type 'boolean
-  :group 'python
   :safe 'booleanp)
 
 (defcustom python-indent-guess-indent-offset-verbose t
   "Non-nil means to emit a warning when indentation guessing fails."
   :version "25.1"
   :type 'boolean
-  :group 'python
   :safe' booleanp)
 
 (defcustom python-indent-trigger-commands
   '(indent-for-tab-command yas-expand yas/expand)
   "Commands that might trigger a `python-indent-line' call."
-  :type '(repeat symbol)
-  :group 'python)
+  :type '(repeat symbol))
 
 (defcustom python-indent-def-block-scale 2
   "Multiplier applied to indentation inside multi-line def blocks."
@@ -2031,7 +2027,6 @@ position, else returns nil."
 (defcustom python-shell-buffer-name "Python"
   "Default buffer name for Python interpreter."
   :type 'string
-  :group 'python
   :safe 'stringp)
 
 (defcustom python-shell-interpreter
@@ -2045,19 +2040,16 @@ Some Python interpreters also require changes to
 `python-shell-interpreter' to \"ipython3\" requires setting
 `python-shell-interpreter-args' to \"--simple-prompt\"."
   :version "28.1"
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (defcustom python-shell-internal-buffer-name "Python Internal"
   "Default buffer name for the Internal Python interpreter."
   :type 'string
-  :group 'python
   :safe 'stringp)
 
 (defcustom python-shell-interpreter-args "-i"
   "Default arguments for the Python interpreter."
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (defcustom python-shell-interpreter-interactive-arg "-i"
   "Interpreter argument to force it to run interactively."
@@ -2122,7 +2114,6 @@ It should not contain a caret (^) at the beginning."
   "Should syntax highlighting be enabled in the Python shell buffer?
 Restart the Python shell after changing this variable for it to take effect."
   :type 'boolean
-  :group 'python
   :safe 'booleanp)
 
 (defcustom python-shell-unbuffered t
@@ -2130,7 +2121,6 @@ Restart the Python shell after changing this variable for 
it to take effect."
 When non-nil, this may prevent delayed and missing output in the
 Python shell.  See commentary for details."
   :type 'boolean
-  :group 'python
   :safe 'booleanp)
 
 (defcustom python-shell-process-environment nil
@@ -2140,8 +2130,7 @@ When this variable is non-nil, values are exported into 
the
 process environment before starting it.  Any variables already
 present in the current environment are superseded by variables
 set here."
-  :type '(repeat string)
-  :group 'python)
+  :type '(repeat string))
 
 (defcustom python-shell-extra-pythonpaths nil
   "List of extra pythonpaths for Python shell.
@@ -2150,8 +2139,7 @@ the PYTHONPATH before starting processes.  Any values 
present
 here that already exists in PYTHONPATH are moved to the beginning
 of the list so that they are prioritized when looking for
 modules."
-  :type '(repeat string)
-  :group 'python)
+  :type '(repeat string))
 
 (defcustom python-shell-exec-path nil
   "List of paths for searching executables.
@@ -2159,8 +2147,7 @@ When this variable is non-nil, values added at the 
beginning of
 the PATH before starting processes.  Any values present here that
 already exists in PATH are moved to the beginning of the list so
 that they are prioritized when looking for executables."
-  :type '(repeat string)
-  :group 'python)
+  :type '(repeat string))
 
 (defcustom python-shell-remote-exec-path nil
   "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
 plan to ensure a particular set of paths to all Python shell
 executed through tramp connections."
   :version "25.1"
-  :type '(repeat string)
-  :group 'python)
+  :type '(repeat string))
 
 (define-obsolete-variable-alias
   'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1")
@@ -2182,13 +2168,11 @@ executed through tramp connections."
 This variable, when set to a string, makes the environment to be
 modified such that shells are started within the specified
 virtualenv."
-  :type '(choice (const nil) directory)
-  :group 'python)
+  :type '(choice (const nil) directory))
 
 (defcustom python-shell-setup-codes nil
   "List of code run by `python-shell-send-setup-code'."
-  :type '(repeat symbol)
-  :group 'python)
+  :type '(repeat symbol))
 
 (defcustom python-shell-compilation-regexp-alist
   `((,(rx line-start (1+ (any " \t")) "File \""
@@ -2202,8 +2186,7 @@ virtualenv."
           "(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
      1 2))
   "`compilation-error-regexp-alist' for inferior Python."
-  :type '(alist regexp)
-  :group 'python)
+  :type '(alist regexp))
 
 (defvar python-shell-output-filter-in-progress nil)
 (defvar python-shell-output-filter-buffer nil)
@@ -2221,33 +2204,33 @@ virtualenv."
           (or (getenv "PYTHONPATH") "") path-separator 'omit)))
     (python-shell--add-to-path-with-priority
      pythonpath python-shell-extra-pythonpaths)
-    (mapconcat 'identity pythonpath path-separator)))
+    (mapconcat #'identity pythonpath path-separator)))
 
 (defun python-shell-calculate-process-environment ()
-  "Calculate `process-environment' or `tramp-remote-process-environment'.
+  (declare (obsolete python-shell--calculate-process-environment "29.1"))
+  (let* ((remote-p (file-remote-p default-directory)))
+    (append (python-shell--calculate-process-environment)
+            (if remote-p
+                tramp-remote-process-environment
+              process-environment))))
+
+(defun python-shell--calculate-process-environment ()
+  "Return a list of entries to add to the `process-environment'.
 Prepends `python-shell-process-environment', sets extra
 pythonpaths from `python-shell-extra-pythonpaths' and sets a few
-virtualenv related vars.  If `default-directory' points to a
-remote host, the returned value is intended for
-`tramp-remote-process-environment'."
-  (let* ((remote-p (file-remote-p default-directory))
-         (process-environment (if remote-p
-                                  tramp-remote-process-environment
-                                process-environment))
-         (virtualenv (when python-shell-virtualenv-root
-                       (directory-file-name python-shell-virtualenv-root))))
-    (dolist (env python-shell-process-environment)
-      (pcase-let ((`(,key ,value) (split-string env "=")))
-        (setenv key value)))
+virtualenv related vars."
+  (let* ((virtualenv (when python-shell-virtualenv-root
+                       (directory-file-name python-shell-virtualenv-root)))
+         (res python-shell-process-environment))
     (when python-shell-unbuffered
-      (setenv "PYTHONUNBUFFERED" "1"))
+      (push "PYTHONUNBUFFERED=1" res))
     (when python-shell-extra-pythonpaths
-      (setenv "PYTHONPATH" (python-shell-calculate-pythonpath)))
+      (push (concat "PYTHONPATH=" (python-shell-calculate-pythonpath)) res))
     (if (not virtualenv)
-        process-environment
-      (setenv "PYTHONHOME" nil)
-      (setenv "VIRTUAL_ENV" virtualenv))
-    process-environment))
+        nil
+      (push "PYTHONHOME" res)
+      (push (concat "VIRTUAL_ENV=" virtualenv) res))
+    res))
 
 (defun python-shell-calculate-exec-path ()
   "Calculate `exec-path'.
@@ -2275,14 +2258,26 @@ of `exec-path'."
 
 (defun python-shell-tramp-refresh-remote-path (vec paths)
   "Update VEC's remote-path giving PATHS priority."
+  (cl-assert (featurep 'tramp))
+  (declare-function tramp-set-remote-path "tramp-sh")
+  (declare-function tramp-set-connection-property "tramp-cache")
+  (declare-function tramp-get-connection-property "tramp-cache")
   (let ((remote-path (tramp-get-connection-property vec "remote-path" nil)))
     (when remote-path
+      ;; FIXME: This part of the Tramp code still knows about Python!
       (python-shell--add-to-path-with-priority remote-path paths)
       (tramp-set-connection-property vec "remote-path" remote-path)
       (tramp-set-remote-path vec))))
 
+
 (defun python-shell-tramp-refresh-process-environment (vec env)
   "Update VEC's process environment with ENV."
+  (cl-assert (featurep 'tramp))
+  (defvar tramp-end-of-heredoc)
+  (defvar tramp-end-of-output)
+  ;; Do we even know that `tramp-sh' is loaded at this point?
+  ;; What about files accessed via FTP, sudo, ...?
+  (declare-function tramp-send-command "tramp-sh")
   ;; Stolen from `tramp-open-connection-setup-interactive-shell'.
   (let ((env (append (when (fboundp 'tramp-get-remote-locale)
                        ;; Emacs<24.4 compat.
@@ -2295,7 +2290,7 @@ of `exec-path'."
        unset vars item)
     (while env
       (setq item (split-string (car env) "=" 'omit))
-      (setcdr item (mapconcat 'identity (cdr item) "="))
+      (setcdr item (mapconcat #'identity (cdr item) "="))
       (if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
          (push (format "%s %s" (car item) (cdr item)) vars)
        (push (car item) unset))
@@ -2305,12 +2300,12 @@ of `exec-path'."
        vec
        (format "while read var val; do export $var=$val; done <<'%s'\n%s\n%s"
               tramp-end-of-heredoc
-              (mapconcat 'identity vars "\n")
+              (mapconcat #'identity vars "\n")
               tramp-end-of-heredoc)
        t))
     (when unset
       (tramp-send-command
-       vec (format "unset %s" (mapconcat 'identity unset " ")) t))))
+       vec (format "unset %s" (mapconcat #'identity unset " ")) t))))
 
 (defmacro python-shell-with-environment (&rest body)
   "Modify shell environment during execution of BODY.
@@ -2319,41 +2314,49 @@ execution of body.  If `default-directory' points to a 
remote
 machine then modifies `tramp-remote-process-environment' and
 `python-shell-remote-exec-path' instead."
   (declare (indent 0) (debug (body)))
-  (let ((vec (make-symbol "vec")))
-    `(progn
-       (let* ((,vec
-               (when (file-remote-p default-directory)
-                 (ignore-errors
-                   (tramp-dissect-file-name default-directory 'noexpand))))
-              (process-environment
-               (if ,vec
-                   process-environment
-                 (python-shell-calculate-process-environment)))
-              (exec-path
-               (if ,vec
-                   exec-path
-                 (python-shell-calculate-exec-path)))
-              (tramp-remote-process-environment
-               (if ,vec
-                   (python-shell-calculate-process-environment)
-                 tramp-remote-process-environment)))
-         (when (tramp-get-connection-process ,vec)
-           ;; For already existing connections, the new exec path must
-           ;; be re-set, otherwise it won't take effect.  One example
-           ;; of such case is when remote dir-locals are read and
-           ;; *then* subprocesses are triggered within the same
-           ;; connection.
-           (python-shell-tramp-refresh-remote-path
-            ,vec (python-shell-calculate-exec-path))
-           ;; The `tramp-remote-process-environment' variable is only
-           ;; effective when the started process is an interactive
-           ;; shell, otherwise (like in the case of processes started
-           ;; with `process-file') the environment is not changed.
-           ;; This makes environment modifications effective
-           ;; unconditionally.
-           (python-shell-tramp-refresh-process-environment
-            ,vec tramp-remote-process-environment))
-         ,(macroexp-progn body)))))
+  `(python-shell--with-environment
+    (python-shell--calculate-process-environment)
+    (lambda () ,@body)))
+
+(defun python-shell--with-environment (extraenv bodyfun)
+  ;; FIXME: This is where the generic code delegates to Tramp.
+  (let* ((vec
+          (and (file-remote-p default-directory)
+               (fboundp 'tramp-dissect-file-name)
+               (ignore-errors
+                 (tramp-dissect-file-name default-directory 'noexpand)))))
+    (if vec
+        (python-shell--tramp-with-environment vec extraenv bodyfun)
+      (let ((process-environment
+             (append extraenv process-environment))
+            (exec-path
+             ;; FIXME: This is still Python-specific.
+             (python-shell-calculate-exec-path)))
+        (funcall bodyfun)))))
+
+(defun python-shell--tramp-with-environment (vec extraenv bodyfun)
+  (defvar tramp-remote-process-environment)
+  (declare-function tramp-get-connection-process "tramp" (vec))
+  (let* ((tramp-remote-process-environment
+          (append extraenv tramp-remote-process-environment)))
+    (when (tramp-get-connection-process vec)
+      ;; For already existing connections, the new exec path must
+      ;; be re-set, otherwise it won't take effect.  One example
+      ;; of such case is when remote dir-locals are read and
+      ;; *then* subprocesses are triggered within the same
+      ;; connection.
+      (python-shell-tramp-refresh-remote-path
+       ;; FIXME: This is still Python-specific.
+       vec (python-shell-calculate-exec-path))
+      ;; The `tramp-remote-process-environment' variable is only
+      ;; effective when the started process is an interactive
+      ;; shell, otherwise (like in the case of processes started
+      ;; with `process-file') the environment is not changed.
+      ;; This makes environment modifications effective
+      ;; unconditionally.
+      (python-shell-tramp-refresh-process-environment
+       vec tramp-remote-process-environment))
+    (funcall bodyfun)))
 
 (defvar python-shell--prompt-calculated-input-regexp nil
   "Calculated input prompt regexp for inferior python shell.
@@ -2636,7 +2639,7 @@ banner and the initial prompt are received separately."
 
 (define-obsolete-function-alias
   'python-comint-output-filter-function
-  'ansi-color-filter-apply
+  #'ansi-color-filter-apply
   "25.1")
 
 (defun python-comint-postoutput-scroll-to-bottom (output)
@@ -2821,8 +2824,7 @@ current process to not hang while waiting.  This is 
useful to
 safely attach setup code for long-running processes that
 eventually provide a shell."
   :version "25.1"
-  :type 'hook
-  :group 'python)
+  :type 'hook)
 
 (defconst python-shell-eval-setup-code
   "\
@@ -2956,7 +2958,7 @@ variable.
   (add-hook 'completion-at-point-functions
             #'python-shell-completion-at-point nil 'local)
   (define-key inferior-python-mode-map "\t"
-    'python-shell-completion-complete-or-indent)
+    #'python-shell-completion-complete-or-indent)
   (make-local-variable 'python-shell-internal-last-output)
   (when python-shell-font-lock-enable
     (python-shell-font-lock-turn-on))
@@ -2982,7 +2984,8 @@ killed."
           (let* ((cmdlist (split-string-and-unquote cmd))
                  (interpreter (car cmdlist))
                  (args (cdr cmdlist))
-                 (buffer (apply #'make-comint-in-buffer proc-name 
proc-buffer-name
+                 (buffer (apply #'make-comint-in-buffer proc-name
+                                proc-buffer-name
                                 interpreter nil args))
                  (python-shell--parent-buffer (current-buffer))
                  (process (get-buffer-process buffer))
@@ -3131,7 +3134,7 @@ there for compatibility with CEDET.")
       (run-python-internal))))
 
 (define-obsolete-function-alias
-  'python-proc 'python-shell-internal-get-or-create-process "24.3")
+  'python-proc #'python-shell-internal-get-or-create-process "24.3")
 
 (defun python-shell--save-temp-file (string)
   (let* ((temporary-file-directory
@@ -3250,10 +3253,10 @@ Returns the output.  See 
`python-shell-send-string-no-output'."
          (python-shell-internal-get-or-create-process))))
 
 (define-obsolete-function-alias
-  'python-send-receive 'python-shell-internal-send-string "24.3")
+  'python-send-receive #'python-shell-internal-send-string "24.3")
 
 (define-obsolete-function-alias
-  'python-send-string 'python-shell-internal-send-string "24.3")
+  'python-send-string #'python-shell-internal-send-string "24.3")
 
 (defun python-shell-buffer-substring (start end &optional nomain no-cookie)
   "Send buffer substring from START to END formatted for shell.
@@ -3549,8 +3552,7 @@ def __PYTHON_EL_get_completions(text):
             completer.print_mode = True
     return completions"
   "Code used to setup completion in inferior Python processes."
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (define-obsolete-variable-alias
   'python-shell-completion-module-string-code
@@ -3823,7 +3825,8 @@ With argument MSG show activation/deactivation message."
               ;; in use based on its args and uses `apply-partially'
               ;; to make it up for the 3 args case.
               (if (= (length
-                      (help-function-arglist 'comint-redirect-filter)) 3)
+                      (help-function-arglist 'comint-redirect-filter))
+                     3)
                   (set-process-filter
                    process (apply-partially
                             #'comint-redirect-filter original-filter-fn))
@@ -3932,7 +3935,7 @@ using that one instead of current buffer's process."
 
 (define-obsolete-function-alias
   'python-shell-completion-complete-at-point
-  'python-shell-completion-at-point
+  #'python-shell-completion-at-point
   "25.1")
 
 (defun python-shell-completion-complete-or-indent ()
@@ -3961,7 +3964,6 @@ considered over.  The overlay arrow will be removed from 
the currently tracked
 buffer.  Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all
 files opened by pdbtracking will be killed."
   :type 'boolean
-  :group 'python
   :safe 'booleanp)
 
 (defcustom python-pdbtrack-stacktrace-info-regexp
@@ -4170,7 +4172,7 @@ inferior Python process is updated properly."
 
 (define-obsolete-function-alias
   'python-completion-complete-at-point
-  'python-completion-at-point
+  #'python-completion-at-point
   "25.1")
 
 
@@ -4180,29 +4182,25 @@ inferior Python process is updated properly."
   "Function to fill comments.
 This is the function used by `python-fill-paragraph' to
 fill comments."
-  :type 'symbol
-  :group 'python)
+  :type 'symbol)
 
 (defcustom python-fill-string-function 'python-fill-string
   "Function to fill strings.
 This is the function used by `python-fill-paragraph' to
 fill strings."
-  :type 'symbol
-  :group 'python)
+  :type 'symbol)
 
 (defcustom python-fill-decorator-function 'python-fill-decorator
   "Function to fill decorators.
 This is the function used by `python-fill-paragraph' to
 fill decorators."
-  :type 'symbol
-  :group 'python)
+  :type 'symbol)
 
 (defcustom python-fill-paren-function 'python-fill-paren
   "Function to fill parens.
 This is the function used by `python-fill-paragraph' to
 fill parens."
-  :type 'symbol
-  :group 'python)
+  :type 'symbol)
 
 (defcustom python-fill-docstring-style 'pep-257
   "Style used to fill docstrings.
@@ -4272,7 +4270,6 @@ value may result in one of the following docstring styles:
           (const :tag "PEP-257 with 2 newlines at end of string." pep-257)
           (const :tag "PEP-257 with 1 newline at end of string." pep-257-nn)
           (const :tag "Symmetric style." symmetric))
-  :group 'python
   :safe (lambda (val)
           (memq val '(django onetwo pep-257 pep-257-nn symmetric nil))))
 
@@ -4431,7 +4428,6 @@ JUSTIFY should be used (if applicable) as in 
`fill-paragraph'."
 This happens when pressing \"if<SPACE>\", for example, to prompt for
 the if condition."
   :type 'boolean
-  :group 'python
   :safe 'booleanp)
 
 (defvar python-skeleton-available '()
@@ -4556,7 +4552,7 @@ The skeleton will be bound to python-skeleton-NAME."
 
 (defun python-skeleton-add-menu-items ()
   "Add menu items to Python->Skeletons menu."
-  (let ((skeletons (sort python-skeleton-available 'string<)))
+  (let ((skeletons (sort python-skeleton-available #'string<)))
     (dolist (skeleton skeletons)
       (easy-menu-add-item
        nil '("Python" "Skeletons")
@@ -4586,8 +4582,7 @@ def __FFAP_get_module_path(objstr):
     except:
         return ''"
   "Python code to get a module path."
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (defun python-ffap-module-path (module)
   "Function for `ffap-alist' to return path for MODULE."
@@ -4615,14 +4610,12 @@ def __FFAP_get_module_path(objstr):
       (executable-find "epylint")
       "install pyflakes, pylint or something else")
   "Command used to check a Python file."
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (defcustom python-check-buffer-name
   "*Python check: %s*"
   "Buffer name used for check commands."
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (defvar python-check-custom-command nil
   "Internal use.")
@@ -4689,8 +4682,7 @@ See `python-check-command' for the default."
         doc = ''
     return doc"
   "Python code to setup documentation retrieval."
-  :type 'string
-  :group 'python)
+  :type 'string)
 
 (defun python-eldoc--get-symbol-at-point ()
   "Get the current symbol for eldoc.
@@ -4737,14 +4729,13 @@ Set to nil by `python-eldoc-function' if
 
 (defcustom python-eldoc-function-timeout 1
   "Timeout for `python-eldoc-function' in seconds."
-  :group 'python
   :type 'integer
   :version "25.1")
 
 (defcustom python-eldoc-function-timeout-permanent t
-  "Non-nil means that when `python-eldoc-function' times out
-`python-eldoc-get-doc' will be set to nil."
-  :group 'python
+  "If non-nil, a timeout in Python-Eldoc will disable it permanently.
+Python-Eldoc can be re-enabled manually by setting `python-eldoc-get-doc'
+back to t in the affected buffer."
   :type 'boolean
   :version "25.1")
 
@@ -4936,7 +4927,7 @@ To this:
      (\"decorator.wrapped_f\" . 393))"
   ;; Inspired by imenu--flatten-index-alist removed in revno 21853.
   (apply
-   'nconc
+   #'nconc
    (mapcar
     (lambda (item)
       (let ((name (if prefix
@@ -5019,7 +5010,7 @@ since it returns nil if point is not inside a defun."
             (and (= (current-indentation) 0) (throw 'exit t))))
         (and names
              (concat (and type (format "%s " type))
-                     (mapconcat 'identity names ".")))))))
+                     (mapconcat #'identity names ".")))))))
 
 (defun python-info-current-symbol (&optional replace-self)
   "Return current symbol using dotty syntax.
@@ -5040,9 +5031,10 @@ parent defun name."
             (replace-regexp-in-string
              (python-rx line-start word-start "self" word-end ?.)
              (concat
-              (mapconcat 'identity
+              (mapconcat #'identity
                          (butlast (split-string current-defun "\\."))
-                         ".") ".")
+                         ".")
+              ".")
              name)))))))
 
 (defun python-info-statement-starts-block-p ()
@@ -5084,7 +5076,7 @@ parent defun name."
 
 (define-obsolete-function-alias
   'python-info-closing-block
-  'python-info-dedenter-opening-block-position "24.4")
+  #'python-info-dedenter-opening-block-position "24.4")
 
 (defun python-info-dedenter-opening-block-position ()
   "Return the point of the closest block the current line closes.
@@ -5129,7 +5121,8 @@ likely an invalid python file."
               (let ((indentation (current-indentation)))
                 (when (and (not (memq indentation collected-indentations))
                            (or (not collected-indentations)
-                               (< indentation (apply #'min 
collected-indentations)))
+                               (< indentation
+                                  (apply #'min collected-indentations)))
                            ;; There must be no line with indentation
                            ;; smaller than `indentation' (except for
                            ;; blank lines) between the found opening
@@ -5157,7 +5150,7 @@ likely an invalid python file."
 
 (define-obsolete-function-alias
   'python-info-closing-block-message
-  'python-info-dedenter-opening-block-message "24.4")
+  #'python-info-dedenter-opening-block-message "24.4")
 
 (defun python-info-dedenter-opening-block-message  ()
   "Message the first line of the block the current statement closes."
@@ -5459,10 +5452,12 @@ allowed files."
   (let ((dir-name (file-name-as-directory dir)))
     (apply #'nconc
            (mapcar (lambda (file-name)
-                     (let ((full-file-name (expand-file-name file-name 
dir-name)))
+                     (let ((full-file-name
+                            (expand-file-name file-name dir-name)))
                        (when (and
                               (not (member file-name '("." "..")))
-                              (funcall (or predicate #'identity) 
full-file-name))
+                              (funcall (or predicate #'identity)
+                                       full-file-name))
                          (list full-file-name))))
                    (directory-files dir-name)))))
 
@@ -5530,7 +5525,6 @@ required arguments.  Once launched it will receive the 
Python source to be
 checked as its standard input.
 To use `flake8' you would set this to (\"flake8\" \"-\")."
   :version "26.1"
-  :group 'python-flymake
   :type '(repeat string))
 
 ;; 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
 information is not present on the matched line and a default will
 be used."
   :version "26.1"
-  :group 'python-flymake
   :type '(list regexp
                (integer :tag "Line's index")
                (choice
@@ -5577,7 +5570,6 @@ configuration could be:
 
 By default messages are considered errors."
   :version "26.1"
-  :group 'python-flymake
   :type '(alist :key-type (regexp)
                 :value-type (symbol)))
 
diff --git a/test/lisp/progmodes/python-tests.el 
b/test/lisp/progmodes/python-tests.el
index 0eb1c087f4..1a6a7dc176 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -2634,58 +2634,59 @@ if x:
   "Test `python-shell-process-environment' modification."
   (let* ((python-shell-process-environment
           '("TESTVAR1=value1" "TESTVAR2=value2"))
-         (process-environment (python-shell-calculate-process-environment)))
-    (should (equal (getenv "TESTVAR1") "value1"))
-    (should (equal (getenv "TESTVAR2") "value2"))))
+         (env (python-shell--calculate-process-environment)))
+    (should (equal (getenv-internal "TESTVAR1" env) "value1"))
+    (should (equal (getenv-internal "TESTVAR2" env) "value2"))))
 
 (ert-deftest python-shell-calculate-process-environment-2 ()
   "Test `python-shell-extra-pythonpaths' modification."
   (let* ((process-environment process-environment)
          (_original-pythonpath (setenv "PYTHONPATH" "/path0"))
          (python-shell-extra-pythonpaths '("/path1" "/path2"))
-         (process-environment (python-shell-calculate-process-environment)))
-    (should (equal (getenv "PYTHONPATH")
+         (env (python-shell--calculate-process-environment)))
+    (should (equal (getenv-internal "PYTHONPATH" env)
                    (concat "/path1" path-separator
                            "/path2" path-separator "/path0")))))
 
 (ert-deftest python-shell-calculate-process-environment-3 ()
   "Test `python-shell-virtualenv-root' modification."
   (let* ((python-shell-virtualenv-root "/env")
-         (process-environment
+         (env
           (let ((process-environment process-environment))
             (setenv "PYTHONHOME" "/home")
             (setenv "VIRTUAL_ENV")
-            (python-shell-calculate-process-environment))))
-    (should (not (getenv "PYTHONHOME")))
-    (should (string= (getenv "VIRTUAL_ENV") "/env"))))
+            (python-shell--calculate-process-environment))))
+    (should (member "PYTHONHOME" env))
+    (should (string= (getenv-internal "VIRTUAL_ENV" env) "/env"))))
 
 (ert-deftest python-shell-calculate-process-environment-4 ()
   "Test PYTHONUNBUFFERED when `python-shell-unbuffered' is non-nil."
   (let* ((python-shell-unbuffered t)
-         (process-environment
+         (env
           (let ((process-environment process-environment))
             (setenv "PYTHONUNBUFFERED")
-            (python-shell-calculate-process-environment))))
-    (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+            (python-shell--calculate-process-environment))))
+    (should (string= (getenv-internal "PYTHONUNBUFFERED" env) "1"))))
 
 (ert-deftest python-shell-calculate-process-environment-5 ()
   "Test PYTHONUNBUFFERED when `python-shell-unbuffered' is nil."
   (let* ((python-shell-unbuffered nil)
-         (process-environment
+         (env
           (let ((process-environment process-environment))
             (setenv "PYTHONUNBUFFERED")
-            (python-shell-calculate-process-environment))))
-    (should (not (getenv "PYTHONUNBUFFERED")))))
+            (python-shell--calculate-process-environment))))
+    (should (not (getenv-internal "PYTHONUNBUFFERED" env)))))
 
 (ert-deftest python-shell-calculate-process-environment-6 ()
   "Test PYTHONUNBUFFERED=1 when `python-shell-unbuffered' is nil."
   (let* ((python-shell-unbuffered nil)
-         (process-environment
+         (env
           (let ((process-environment process-environment))
             (setenv "PYTHONUNBUFFERED" "1")
-            (python-shell-calculate-process-environment))))
+            (append (python-shell--calculate-process-environment)
+                    process-environment))))
     ;; User default settings must remain untouched:
-    (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+    (should (string= (getenv-internal "PYTHONUNBUFFERED" env) "1"))))
 
 (ert-deftest python-shell-calculate-process-environment-7 ()
   "Test no side-effects on `process-environment'."
@@ -2695,7 +2696,7 @@ if x:
          (python-shell-unbuffered t)
          (python-shell-extra-pythonpaths'("/path1" "/path2"))
          (original-process-environment (copy-sequence process-environment)))
-    (python-shell-calculate-process-environment)
+    (python-shell--calculate-process-environment)
     (should (equal process-environment original-process-environment))))
 
 (ert-deftest python-shell-calculate-process-environment-8 ()
@@ -2708,7 +2709,7 @@ if x:
          (python-shell-extra-pythonpaths'("/path1" "/path2"))
          (original-process-environment
           (copy-sequence tramp-remote-process-environment)))
-    (python-shell-calculate-process-environment)
+    (python-shell--calculate-process-environment)
     (should (equal tramp-remote-process-environment 
original-process-environment))))
 
 (ert-deftest python-shell-calculate-exec-path-1 ()
@@ -2780,23 +2781,43 @@ if x:
       (should (string= (getenv "VIRTUAL_ENV") "/env")))
     (should (equal exec-path original-exec-path))))
 
+(defun python--tests-process-env-canonical (pe)
+  ;; `process-environment' can contain various entries for the same
+  ;; var, and the first in the list hides the others.
+  (let ((process-environment '()))
+    (dolist (x (reverse pe))
+      (if (string-match "=" x)
+          (setenv (substring x 0 (match-beginning 0))
+                  (substring x (match-end 0)))
+        (setenv x nil)))
+    process-environment))
+
+(defun python--tests-process-env-eql (pe1 pe2)
+  (equal (python--tests-process-env-canonical pe1)
+         (python--tests-process-env-canonical pe2)))
+
 (ert-deftest python-shell-with-environment-2 ()
   "Test environment with remote `default-directory'."
   (let* ((default-directory "/ssh::/example/dir/")
          (python-shell-remote-exec-path '("/remote1" "/remote2"))
          (python-shell-exec-path '("/path1" "/path2"))
          (tramp-remote-process-environment '("EMACS=t"))
-         (original-process-environment (copy-sequence 
tramp-remote-process-environment))
+         (original-process-environment
+          (copy-sequence tramp-remote-process-environment))
          (python-shell-virtualenv-root "/env"))
     (python-shell-with-environment
       (should (equal (python-shell-calculate-exec-path)
                      (list (python-virt-bin)
                            "/path1" "/path2" "/remote1" "/remote2")))
-      (let ((process-environment (python-shell-calculate-process-environment)))
+      (let ((process-environment
+             (append (python-shell--calculate-process-environment)
+                     tramp-remote-process-environment)))
         (should (not (getenv "PYTHONHOME")))
         (should (string= (getenv "VIRTUAL_ENV") "/env"))
-        (should (equal tramp-remote-process-environment process-environment))))
-    (should (equal tramp-remote-process-environment 
original-process-environment))))
+        (should (python--tests-process-env-eql
+                 tramp-remote-process-environment process-environment))))
+    (should (equal tramp-remote-process-environment
+                   original-process-environment))))
 
 (ert-deftest python-shell-with-environment-3 ()
   "Test `python-shell-with-environment' is idempotent."
@@ -2805,11 +2826,14 @@ if x:
          (python-shell-virtualenv-root "/home/user/env")
          (single-call
           (python-shell-with-environment
-            (list exec-path process-environment)))
+            (list exec-path
+                  (python--tests-process-env-canonical process-environment))))
          (nested-call
           (python-shell-with-environment
             (python-shell-with-environment
-              (list exec-path process-environment)))))
+              (list exec-path
+                    (python--tests-process-env-canonical
+                     process-environment))))))
     (should (equal single-call nested-call))))
 
 (ert-deftest python-shell-make-comint-1 ()



reply via email to

[Prev in Thread] Current Thread [Next in Thread]