diff options
| author | Fabián Ezequiel Gallina | 2015-08-21 19:06:57 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2015-08-21 19:06:57 -0300 |
| commit | 4150b563e7877a0c65233c9e7bd3fa64a7a14342 (patch) | |
| tree | 5bf4f3e98515a341cd438dbc17c4eadf3a2e6e15 /lisp/progmodes/python.el | |
| parent | c1cacb09948928287bfc32745f2a92604d3291c4 (diff) | |
| download | emacs-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.el | 207 |
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. |
| 1961 | This variable follows the same rules as `process-environment' | 1961 | Each element should be a string of the form ENVVARNAME=VALUE. |
| 1962 | since it merges with it before the process creation routines are | 1962 | When this variable is non-nil, values are exported into the |
| 1963 | called. When this variable is nil, the Python shell is run with | 1963 | process environment before starting it. Any variables already |
| 1964 | the default `process-environment'." | 1964 | present in the current environment are superseded by variables |
| 1965 | set 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. |
| 1971 | The values of this variable are added to the existing value of | 1971 | When this variable is non-nil, values added at the beginning of |
| 1972 | PYTHONPATH in the `process-environment' variable." | 1972 | the PYTHONPATH before starting processes. Any values present |
| 1973 | here that already exists in PYTHONPATH are moved to the beginning | ||
| 1974 | of the list so that they are prioritized when looking for | ||
| 1975 | modules." | ||
| 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. |
| 1979 | This variable follows the same rules as `exec-path' since it | 1981 | When this variable is non-nil, values added at the beginning of |
| 1980 | merges with it before the process creation routines are called. | 1982 | the PATH before starting processes. Any values present here that |
| 1981 | When this variable is nil, the Python shell is run with the | 1983 | already exists in PATH are moved to the beginning of the list so |
| 1982 | default `exec-path'." | 1984 | that 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. | ||
| 1990 | When this variable is non-nil, values are exported into remote | ||
| 1991 | hosts PATH before starting processes. Values defined in | ||
| 1992 | `python-shell-exec-path' will take precedence to paths defined | ||
| 1993 | here. Normally you wont use this variable directly unless you | ||
| 1994 | plan to ensure a particular set of paths to all Python shell | ||
| 1995 | executed 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. |
| 1989 | This variable, when set to a string, makes the values stored in | 2001 | This variable, when set to a string, makes the environment to be |
| 1990 | `python-shell-process-environment' and `python-shell-exec-path' | 2002 | modified such that shells are started within the specified |
| 1991 | to be modified properly so shells are started with the specified | ||
| 1992 | virtualenv." | 2003 | virtualenv." |
| 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'. |
| 2025 | Pre-appends `python-shell-process-environment', sets extra | 2049 | Prepends `python-shell-process-environment', sets extra |
| 2026 | pythonpaths from `python-shell-extra-pythonpaths' and sets a few | 2050 | pythonpaths from `python-shell-extra-pythonpaths' and sets a few |
| 2027 | virtualenv related vars. If `default-directory' points to a | 2051 | virtualenv related vars. If `default-directory' points to a |
| 2028 | remote machine, the returned value is intended for | 2052 | remote 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'. |
| 2051 | Pre-appends `python-shell-exec-path' and adds the binary | 2075 | Prepends `python-shell-exec-path' and adds the binary directory |
| 2052 | directory for virtualenv if `python-shell-virtualenv-root' is | 2076 | for virtualenv if `python-shell-virtualenv-root' is set. If |
| 2053 | set. If `default-directory' points to a remote machine, the | 2077 | `default-directory' points to a remote host, the returned value |
| 2054 | returned value is intended for `tramp-remote-path'." | 2078 | appends `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. |
| 2070 | Temporarily sets `process-environment' and `exec-path' during | 2104 | Temporarily sets `process-environment' and `exec-path' during |
| 2071 | execution of body. If `default-directory' points to a remote | 2105 | execution of body. If `default-directory' points to a remote |
| 2072 | machine then modifies `tramp-remote-process-environment' and | 2106 | machine 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) |