aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2015-08-21 19:06:57 -0300
committerFabián Ezequiel Gallina2015-08-21 19:06:57 -0300
commit4150b563e7877a0c65233c9e7bd3fa64a7a14342 (patch)
tree5bf4f3e98515a341cd438dbc17c4eadf3a2e6e15 /lisp/progmodes/python.el
parentc1cacb09948928287bfc32745f2a92604d3291c4 (diff)
downloademacs-4150b563e7877a0c65233c9e7bd3fa64a7a14342.tar.gz
emacs-4150b563e7877a0c65233c9e7bd3fa64a7a14342.zip
python.el: Enhancements to process environment setup.
* lisp/progmodes/python.el (python-shell-process-environment) (python-shell-extra-pythonpaths, python-shell-exec-path) (python-shell-virtualenv-root): Update docstring. Remove :safe. (python-shell-setup-codes): Remove :safe. (python-shell-remote-exec-path): New defcustom. (python-shell--add-to-path-with-priority): New macro. (python-shell-calculate-pythonpath): Give priority to python-shell-extra-pythonpaths. Update docstring. (python-shell-calculate-process-environment): Give priority to python-shell-process-environment. Update docstring. (python-shell-calculate-exec-path): Give priority to python-shell-exec-path and calculated virtualenv bin directory. Update docstring. (python-shell-tramp-refresh-remote-path): New function. (python-shell-with-environment): Use it when working remotely and do not modify tramp-remote-path. Allow nesting. (python-shell-calculate-command): Remove useless python-shell-with-environment call. * test/automated/python-tests.el (python-shell-calculate-pythonpath-1) (python-shell-calculate-pythonpath-2) (python-shell-calculate-process-environment-6) (python-shell-calculate-process-environment-7) (python-shell-calculate-process-environment-8) (python-shell-calculate-exec-path-3) (python-shell-calculate-exec-path-4) (python-shell-calculate-exec-path-5) (python-shell-calculate-exec-path-6) (python-shell-with-environment-3): New tests. (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-exec-path-1) (python-shell-calculate-exec-path-2) (python-shell-with-environment-1) (python-shell-with-environment-2): Update and simplify.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el207
1 files changed, 119 insertions, 88 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 189cd3759f5..e6592fbd2c9 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1957,42 +1957,52 @@ Python shell. See commentary for details."
1957 :safe 'booleanp) 1957 :safe 'booleanp)
1958 1958
1959(defcustom python-shell-process-environment nil 1959(defcustom python-shell-process-environment nil
1960 "List of environment variables for Python shell. 1960 "List of overridden environment variables for subprocesses to inherit.
1961This variable follows the same rules as `process-environment' 1961Each element should be a string of the form ENVVARNAME=VALUE.
1962since it merges with it before the process creation routines are 1962When this variable is non-nil, values are exported into the
1963called. When this variable is nil, the Python shell is run with 1963process environment before starting it. Any variables already
1964the default `process-environment'." 1964present in the current environment are superseded by variables
1965set here."
1965 :type '(repeat string) 1966 :type '(repeat string)
1966 :group 'python 1967 :group 'python)
1967 :safe 'listp)
1968 1968
1969(defcustom python-shell-extra-pythonpaths nil 1969(defcustom python-shell-extra-pythonpaths nil
1970 "List of extra pythonpaths for Python shell. 1970 "List of extra pythonpaths for Python shell.
1971The values of this variable are added to the existing value of 1971When this variable is non-nil, values added at the beginning of
1972PYTHONPATH in the `process-environment' variable." 1972the PYTHONPATH before starting processes. Any values present
1973here that already exists in PYTHONPATH are moved to the beginning
1974of the list so that they are prioritized when looking for
1975modules."
1973 :type '(repeat string) 1976 :type '(repeat string)
1974 :group 'python 1977 :group 'python)
1975 :safe 'listp)
1976 1978
1977(defcustom python-shell-exec-path nil 1979(defcustom python-shell-exec-path nil
1978 "List of path to search for binaries. 1980 "List of paths for searching executables.
1979This variable follows the same rules as `exec-path' since it 1981When this variable is non-nil, values added at the beginning of
1980merges with it before the process creation routines are called. 1982the PATH before starting processes. Any values present here that
1981When this variable is nil, the Python shell is run with the 1983already exists in PATH are moved to the beginning of the list so
1982default `exec-path'." 1984that they are prioritized when looking for executables."
1983 :type '(repeat string) 1985 :type '(repeat string)
1984 :group 'python 1986 :group 'python)
1985 :safe 'listp) 1987
1988(defcustom python-shell-remote-exec-path nil
1989 "List of paths to be ensured remotely for searching executables.
1990When this variable is non-nil, values are exported into remote
1991hosts PATH before starting processes. Values defined in
1992`python-shell-exec-path' will take precedence to paths defined
1993here. Normally you wont use this variable directly unless you
1994plan to ensure a particular set of paths to all Python shell
1995executed through tramp connections."
1996 :type '(repeat string)
1997 :group 'python)
1986 1998
1987(defcustom python-shell-virtualenv-root nil 1999(defcustom python-shell-virtualenv-root nil
1988 "Path to virtualenv root. 2000 "Path to virtualenv root.
1989This variable, when set to a string, makes the values stored in 2001This variable, when set to a string, makes the environment to be
1990`python-shell-process-environment' and `python-shell-exec-path' 2002modified such that shells are started within the specified
1991to be modified properly so shells are started with the specified
1992virtualenv." 2003virtualenv."
1993 :type '(choice (const nil) string) 2004 :type '(choice (const nil) string)
1994 :group 'python 2005 :group 'python)
1995 :safe 'stringp)
1996 2006
1997(define-obsolete-variable-alias 2007(define-obsolete-variable-alias
1998 'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1") 2008 'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1")
@@ -2002,8 +2012,7 @@ virtualenv."
2002 python-eldoc-setup-code) 2012 python-eldoc-setup-code)
2003 "List of code run by `python-shell-send-setup-codes'." 2013 "List of code run by `python-shell-send-setup-codes'."
2004 :type '(repeat symbol) 2014 :type '(repeat symbol)
2005 :group 'python 2015 :group 'python)
2006 :safe 'listp)
2007 2016
2008(defcustom python-shell-compilation-regexp-alist 2017(defcustom python-shell-compilation-regexp-alist
2009 `((,(rx line-start (1+ (any " \t")) "File \"" 2018 `((,(rx line-start (1+ (any " \t")) "File \""
@@ -2020,22 +2029,37 @@ virtualenv."
2020 :type '(alist string) 2029 :type '(alist string)
2021 :group 'python) 2030 :group 'python)
2022 2031
2032(defmacro python-shell--add-to-path-with-priority (pathvar paths)
2033 "Modify PATHVAR and ensure PATHS are added only once at beginning."
2034 `(dolist (path (reverse ,paths))
2035 (cl-delete path ,pathvar :test #'string=)
2036 (cl-pushnew path ,pathvar :test #'string=)))
2037
2038(defun python-shell-calculate-pythonpath ()
2039 "Calculate the PYTHONPATH using `python-shell-extra-pythonpaths'."
2040 (let ((pythonpath
2041 (tramp-compat-split-string
2042 (or (getenv "PYTHONPATH") "") path-separator)))
2043 (python-shell--add-to-path-with-priority
2044 pythonpath python-shell-extra-pythonpaths)
2045 (mapconcat 'identity pythonpath path-separator)))
2046
2023(defun python-shell-calculate-process-environment () 2047(defun python-shell-calculate-process-environment ()
2024 "Calculate `process-environment' or `tramp-remote-process-environment'. 2048 "Calculate `process-environment' or `tramp-remote-process-environment'.
2025Pre-appends `python-shell-process-environment', sets extra 2049Prepends `python-shell-process-environment', sets extra
2026pythonpaths from `python-shell-extra-pythonpaths' and sets a few 2050pythonpaths from `python-shell-extra-pythonpaths' and sets a few
2027virtualenv related vars. If `default-directory' points to a 2051virtualenv related vars. If `default-directory' points to a
2028remote machine, the returned value is intended for 2052remote host, the returned value is intended for
2029`tramp-remote-process-environment'." 2053`tramp-remote-process-environment'."
2030 (let* ((remote-p (file-remote-p default-directory)) 2054 (let* ((remote-p (file-remote-p default-directory))
2031 (process-environment (append 2055 (process-environment (if remote-p
2032 python-shell-process-environment 2056 tramp-remote-process-environment
2033 (if remote-p 2057 process-environment))
2034 tramp-remote-process-environment 2058 (virtualenv (when python-shell-virtualenv-root
2035 process-environment) nil)) 2059 (directory-file-name python-shell-virtualenv-root))))
2036 (virtualenv (if python-shell-virtualenv-root 2060 (dolist (env python-shell-process-environment)
2037 (directory-file-name python-shell-virtualenv-root) 2061 (pcase-let ((`(,key ,value) (split-string env "=")))
2038 nil))) 2062 (setenv key value)))
2039 (when python-shell-unbuffered 2063 (when python-shell-unbuffered
2040 (setenv "PYTHONUNBUFFERED" "1")) 2064 (setenv "PYTHONUNBUFFERED" "1"))
2041 (when python-shell-extra-pythonpaths 2065 (when python-shell-extra-pythonpaths
@@ -2047,50 +2071,71 @@ remote machine, the returned value is intended for
2047 process-environment)) 2071 process-environment))
2048 2072
2049(defun python-shell-calculate-exec-path () 2073(defun python-shell-calculate-exec-path ()
2050 "Calculate `exec-path' or `tramp-remote-path'. 2074 "Calculate `exec-path'.
2051Pre-appends `python-shell-exec-path' and adds the binary 2075Prepends `python-shell-exec-path' and adds the binary directory
2052directory for virtualenv if `python-shell-virtualenv-root' is 2076for virtualenv if `python-shell-virtualenv-root' is set. If
2053set. If `default-directory' points to a remote machine, the 2077`default-directory' points to a remote host, the returned value
2054returned value is intended for `tramp-remote-path'." 2078appends `python-shell-remote-exec-path' instead of `exec-path'."
2055 (let ((path (append 2079 (let ((new-path (copy-sequence
2056 ;; Use nil as the tail so that the list is a full copy, 2080 (if (file-remote-p default-directory)
2057 ;; this is a paranoid safeguard for side-effects. 2081 python-shell-remote-exec-path
2058 python-shell-exec-path 2082 exec-path))))
2059 (if (file-remote-p default-directory) 2083 (python-shell--add-to-path-with-priority
2060 tramp-remote-path 2084 new-path python-shell-exec-path)
2061 exec-path)
2062 nil)))
2063 (if (not python-shell-virtualenv-root) 2085 (if (not python-shell-virtualenv-root)
2064 path 2086 new-path
2065 (cons (expand-file-name "bin" python-shell-virtualenv-root) 2087 (python-shell--add-to-path-with-priority
2066 path)))) 2088 new-path
2089 (list (expand-file-name "bin" python-shell-virtualenv-root)))
2090 new-path)))
2091
2092(defun python-shell-tramp-refresh-remote-path (vec paths)
2093 "Update VEC's remote-path giving PATHS priority."
2094 (let ((remote-path (tramp-get-connection-property vec "remote-path" nil)))
2095 (when remote-path
2096 (python-shell--add-to-path-with-priority remote-path paths)
2097 (tramp-set-connection-property vec "remote-path" remote-path)
2098 (tramp-set-remote-path vec))))
2099
2100(defvar python-shell--with-environment-wrapped nil)
2067 2101
2068(defmacro python-shell-with-environment (&rest body) 2102(defmacro python-shell-with-environment (&rest body)
2069 "Modify shell environment during execution of BODY. 2103 "Modify shell environment during execution of BODY.
2070Temporarily sets `process-environment' and `exec-path' during 2104Temporarily sets `process-environment' and `exec-path' during
2071execution of body. If `default-directory' points to a remote 2105execution of body. If `default-directory' points to a remote
2072machine then modifies `tramp-remote-process-environment' and 2106machine then modifies `tramp-remote-process-environment' and
2073`tramp-remote-path' instead." 2107`python-shell-remote-exec-path' instead."
2074 (declare (indent 0) (debug (body))) 2108 (declare (indent 0) (debug (body)))
2075 (let ((remote-p (make-symbol "remote-p"))) 2109 (let ((vec (make-symbol "vec")))
2076 `(let* ((,remote-p (file-remote-p default-directory)) 2110 `(progn
2077 (process-environment 2111 (if python-shell--with-environment-wrapped
2078 (if ,remote-p 2112 ,(macroexp-progn body)
2079 process-environment 2113 (let* ((,vec
2080 (python-shell-calculate-process-environment))) 2114 (when (file-remote-p default-directory)
2081 (tramp-remote-process-environment 2115 (ignore-errors
2082 (if ,remote-p 2116 (tramp-dissect-file-name default-directory 'noexpand))))
2083 (python-shell-calculate-process-environment) 2117 (process-environment
2084 tramp-remote-process-environment)) 2118 (if ,vec
2085 (exec-path 2119 process-environment
2086 (if ,remote-p 2120 (python-shell-calculate-process-environment)))
2087 exec-path 2121 (exec-path
2088 (python-shell-calculate-exec-path))) 2122 (if ,vec
2089 (tramp-remote-path 2123 exec-path
2090 (if ,remote-p 2124 (python-shell-calculate-exec-path)))
2091 (python-shell-calculate-exec-path) 2125 (tramp-remote-process-environment
2092 tramp-remote-path))) 2126 (if ,vec
2093 ,(macroexp-progn body)))) 2127 (python-shell-calculate-process-environment)
2128 tramp-remote-process-environment))
2129 (python-shell--with-environment-wrapped t))
2130 (when (tramp-get-connection-process ,vec)
2131 ;; For already existing connections, modified env vars must
2132 ;; be re-set again. This is a normal thing to happen when
2133 ;; remote dir-locals are read from remote and *then*
2134 ;; processes should be started within the same connection
2135 ;; with env vars calculated from them.
2136 (python-shell-tramp-refresh-remote-path
2137 ,vec (python-shell-calculate-exec-path)))
2138 ,(macroexp-progn body))))))
2094 2139
2095(defvar python-shell--prompt-calculated-input-regexp nil 2140(defvar python-shell--prompt-calculated-input-regexp nil
2096 "Calculated input prompt regexp for inferior python shell. 2141 "Calculated input prompt regexp for inferior python shell.
@@ -2271,28 +2316,14 @@ the `buffer-name'."
2271 2316
2272(defun python-shell-calculate-command () 2317(defun python-shell-calculate-command ()
2273 "Calculate the string used to execute the inferior Python process." 2318 "Calculate the string used to execute the inferior Python process."
2274 (python-shell-with-environment 2319 (format "%s %s"
2275 ;; `exec-path' gets tweaked so that virtualenv's specific 2320 (shell-quote-argument python-shell-interpreter)
2276 ;; `python-shell-interpreter' absolute path can be found by 2321 python-shell-interpreter-args))
2277 ;; `executable-find'.
2278 (format "%s %s"
2279 (shell-quote-argument python-shell-interpreter)
2280 python-shell-interpreter-args)))
2281 2322
2282(define-obsolete-function-alias 2323(define-obsolete-function-alias
2283 'python-shell-parse-command 2324 'python-shell-parse-command
2284 #'python-shell-calculate-command "25.1") 2325 #'python-shell-calculate-command "25.1")
2285 2326
2286(defun python-shell-calculate-pythonpath ()
2287 "Calculate the PYTHONPATH using `python-shell-extra-pythonpaths'."
2288 (let ((pythonpath (getenv "PYTHONPATH"))
2289 (extra (mapconcat 'identity
2290 python-shell-extra-pythonpaths
2291 path-separator)))
2292 (if pythonpath
2293 (concat extra path-separator pythonpath)
2294 extra)))
2295
2296(defvar python-shell--package-depth 10) 2327(defvar python-shell--package-depth 10)
2297 2328
2298(defun python-shell-package-enable (directory package) 2329(defun python-shell-package-enable (directory package)