aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2014-07-19 10:13:07 -0300
committerFabián Ezequiel Gallina2014-07-19 10:13:07 -0300
commitd949ade3c101981d015b3d78d061bdff584df13a (patch)
treed5e486ede2477b8f139720eabda8f6965086daef
parent64384ca4ded41824f30a0a2470a65160dd486207 (diff)
downloademacs-d949ade3c101981d015b3d78d061bdff584df13a.tar.gz
emacs-d949ade3c101981d015b3d78d061bdff584df13a.zip
Autodetect Python shell prompts.
* lisp/progmodes/python.el: (python-shell-interpreter-interactive-arg) (python-shell-prompt-detect-enabled) (python-shell-prompt-detect-failure-warning) (python-shell-prompt-input-regexps) (python-shell-prompt-output-regexps): New vars. (python-shell-prompt-calculated-input-regexp) (python-shell-prompt-calculated-output-regexp): New vars. (python-shell-get-process-name) (python-shell-internal-get-process-name) (python-shell-output-filter) (python-shell-completion-get-completions): Use them. (python-shell-prompt-detect) (python-shell-prompt-validate-regexps): New functions. (python-shell-prompt-set-calculated-regexps): New function. (inferior-python-mode): Use it. Also honor overriden python-shell-interpreter and python-shell-interpreter-args. (python-shell-make-comint): Honor overriden python-shell-interpreter and python-shell-interpreter-args. (python-shell-get-or-create-process): Make it testable by allowing to call run-python non-interactively. (python-util-valid-regexp-p): New function. (python-shell-prompt-regexp, python-shell-prompt-block-regexp) (python-shell-prompt-output-regexp) (python-shell-prompt-pdb-regexp): Use it as defcustom :safe. * test/automated/python-tests.el (python-shell-make-comint-1): (python-shell-make-comint-2): Fix indentation. (python-shell-make-comint-3) (python-shell-make-comint-4): New tests. (python-shell-get-or-create-process-1): Fix test. (python-shell-get-or-create-process-2) (python-shell-get-or-create-process-3): New tests. (python-shell-internal-get-or-create-process-1): Fix test. (python-shell-prompt-detect-1): New test. (python-shell-prompt-detect-2): New test. (Bug#17370) (python-shell-prompt-detect-3) (python-shell-prompt-detect-4) (python-shell-prompt-detect-5) (python-shell-prompt-detect-6) (python-shell-prompt-validate-regexps-1) (python-shell-prompt-validate-regexps-2) (python-shell-prompt-validate-regexps-3) (python-shell-prompt-validate-regexps-4) (python-shell-prompt-validate-regexps-5) (python-shell-prompt-validate-regexps-6) (python-shell-prompt-validate-regexps-7) (python-shell-prompt-set-calculated-regexps-1) (python-shell-prompt-set-calculated-regexps-2) (python-shell-prompt-set-calculated-regexps-3) (python-shell-prompt-set-calculated-regexps-4) (python-shell-prompt-set-calculated-regexps-5) (python-shell-prompt-set-calculated-regexps-6) (python-util-valid-regexp-p-1): New tests.
-rw-r--r--lisp/ChangeLog29
-rw-r--r--lisp/progmodes/python.el316
-rw-r--r--test/ChangeLog34
-rw-r--r--test/automated/python-tests.el486
4 files changed, 772 insertions, 93 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 0e82c4bbc46..2a1266a6031 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,32 @@
12014-07-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
2
3 Autodetect Python shell prompts. (Bug#17370)
4 * progmodes/python.el:
5 (python-shell-interpreter-interactive-arg)
6 (python-shell-prompt-detect-enabled)
7 (python-shell-prompt-detect-failure-warning)
8 (python-shell-prompt-input-regexps)
9 (python-shell-prompt-output-regexps): New vars.
10 (python-shell-prompt-calculated-input-regexp)
11 (python-shell-prompt-calculated-output-regexp): New vars.
12 (python-shell-get-process-name)
13 (python-shell-internal-get-process-name)
14 (python-shell-output-filter)
15 (python-shell-completion-get-completions): Use them.
16 (python-shell-prompt-detect)
17 (python-shell-prompt-validate-regexps): New functions.
18 (python-shell-prompt-set-calculated-regexps): New function.
19 (inferior-python-mode): Use it. Also honor overriden
20 python-shell-interpreter and python-shell-interpreter-args.
21 (python-shell-make-comint): Honor overriden
22 python-shell-interpreter and python-shell-interpreter-args.
23 (python-shell-get-or-create-process): Make it testable by allowing
24 to call run-python non-interactively.
25 (python-util-valid-regexp-p): New function.
26 (python-shell-prompt-regexp, python-shell-prompt-block-regexp)
27 (python-shell-prompt-output-regexp)
28 (python-shell-prompt-pdb-regexp): Use it as defcustom :safe.
29
12014-07-16 Glenn Morris <rgm@gnu.org> 302014-07-16 Glenn Morris <rgm@gnu.org>
2 31
3 * desktop.el (after-init-hook): Disable startup frame restoration 32 * desktop.el (after-init-hook): Disable startup frame restoration
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 237302f0530..e49d5882a61 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4,7 +4,7 @@
4 4
5;; Author: Fabián E. Gallina <fabian@anue.biz> 5;; Author: Fabián E. Gallina <fabian@anue.biz>
6;; URL: https://github.com/fgallina/python.el 6;; URL: https://github.com/fgallina/python.el
7;; Version: 0.24.2 7;; Version: 0.24.4
8;; Maintainer: emacs-devel@gnu.org 8;; Maintainer: emacs-devel@gnu.org
9;; Created: Jul 2010 9;; Created: Jul 2010
10;; Keywords: languages 10;; Keywords: languages
@@ -62,13 +62,28 @@
62;; (add-hook 'python-mode-hook 62;; (add-hook 'python-mode-hook
63;; (lambda () (setq forward-sexp-function nil))) 63;; (lambda () (setq forward-sexp-function nil)))
64 64
65;; Shell interaction: is provided and allows you to execute easily any 65;; Shell interaction: is provided and allows you to easily execute any
66;; block of code of your current buffer in an inferior Python process. 66;; block of code of your current buffer in an inferior Python process.
67;; This relies upon having prompts for input (e.g. ">>> " and "... "
68;; in standard Python shell) and output (e.g. "Out[1]: " in iPython)
69;; detected properly. Failing that Emacs may hang but, in the case
70;; that happens, you can recover with \\[keyboard-quit]. To avoid
71;; this issue, a two-step prompt autodetection mechanism is provided:
72;; the first step is manual and consists of a collection of regular
73;; expressions matching common prompts for Python shells stored in
74;; `python-shell-prompt-input-regexps' and
75;; `python-shell-prompt-output-regexps', and dir-local friendly vars
76;; `python-shell-prompt-regexp', `python-shell-prompt-block-regexp',
77;; `python-shell-prompt-output-regexp' which are appended to the
78;; former automatically when a shell spawns; the second step is
79;; automatic and depends on the `python-shell-prompt-detect' helper
80;; function. See its docstring for details on global variables that
81;; modify its behavior.
67 82
68;; Shell completion: hitting tab will try to complete the current 83;; Shell completion: hitting tab will try to complete the current
69;; word. Shell completion is implemented in a manner that if you 84;; word. Shell completion is implemented in a way that if you change
70;; change the `python-shell-interpreter' to any other (for example 85;; the `python-shell-interpreter' to any other (for example IPython)
71;; IPython) it should be easy to integrate another way to calculate 86;; it should be easy to integrate another way to calculate
72;; completions. You just need to specify your custom 87;; completions. You just need to specify your custom
73;; `python-shell-completion-setup-code' and 88;; `python-shell-completion-setup-code' and
74;; `python-shell-completion-string-code'. 89;; `python-shell-completion-string-code'.
@@ -79,8 +94,6 @@
79;; (setq 94;; (setq
80;; python-shell-interpreter "ipython" 95;; python-shell-interpreter "ipython"
81;; python-shell-interpreter-args "" 96;; python-shell-interpreter-args ""
82;; python-shell-prompt-regexp "In \\[[0-9]+\\]: "
83;; python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
84;; python-shell-completion-setup-code 97;; python-shell-completion-setup-code
85;; "from IPython.core.completerlib import module_completion" 98;; "from IPython.core.completerlib import module_completion"
86;; python-shell-completion-module-string-code 99;; python-shell-completion-module-string-code
@@ -213,7 +226,9 @@
213;;; Code: 226;;; Code:
214 227
215(require 'ansi-color) 228(require 'ansi-color)
229(require 'cl-lib)
216(require 'comint) 230(require 'comint)
231(require 'json)
217 232
218;; Avoid compiler warnings 233;; Avoid compiler warnings
219(defvar view-return-to-alist) 234(defvar view-return-to-alist)
@@ -1706,33 +1721,56 @@ position, else returns nil."
1706 :type 'string 1721 :type 'string
1707 :group 'python) 1722 :group 'python)
1708 1723
1724(defcustom python-shell-interpreter-interactive-arg "-i"
1725 "Interpreter argument to force it to run interactively."
1726 :type 'string
1727 :version "24.4")
1728
1729(defcustom python-shell-prompt-detect-enabled t
1730 "Non-nil enables autodetection of interpreter prompts."
1731 :type 'boolean
1732 :safe 'booleanp
1733 :version "24.4")
1734
1735(defcustom python-shell-prompt-detect-failure-warning t
1736 "Non-nil enables warnings when detection of prompts fail."
1737 :type 'boolean
1738 :safe 'booleanp
1739 :version "24.4")
1740
1741(defcustom python-shell-prompt-input-regexps
1742 '(">>> " "\\.\\.\\. " ; Python
1743 "In \\[[0-9]+\\]: ") ; iPython
1744 "List of regular expressions matching input prompts."
1745 :type '(repeat string)
1746 :version "24.4")
1747
1748(defcustom python-shell-prompt-output-regexps
1749 '("" ; Python
1750 "Out\\[[0-9]+\\]: ") ; iPython
1751 "List of regular expressions matching output prompts."
1752 :type '(repeat string)
1753 :version "24.4")
1754
1709(defcustom python-shell-prompt-regexp ">>> " 1755(defcustom python-shell-prompt-regexp ">>> "
1710 "Regular expression matching top-level input prompt of Python shell. 1756 "Regular expression matching top level input prompt of Python shell.
1711It should not contain a caret (^) at the beginning." 1757It should not contain a caret (^) at the beginning."
1712 :type 'string 1758 :type 'string)
1713 :group 'python
1714 :safe 'stringp)
1715 1759
1716(defcustom python-shell-prompt-block-regexp "[.][.][.] " 1760(defcustom python-shell-prompt-block-regexp "\\.\\.\\. "
1717 "Regular expression matching block input prompt of Python shell. 1761 "Regular expression matching block input prompt of Python shell.
1718It should not contain a caret (^) at the beginning." 1762It should not contain a caret (^) at the beginning."
1719 :type 'string 1763 :type 'string)
1720 :group 'python
1721 :safe 'stringp)
1722 1764
1723(defcustom python-shell-prompt-output-regexp "" 1765(defcustom python-shell-prompt-output-regexp ""
1724 "Regular expression matching output prompt of Python shell. 1766 "Regular expression matching output prompt of Python shell.
1725It should not contain a caret (^) at the beginning." 1767It should not contain a caret (^) at the beginning."
1726 :type 'string 1768 :type 'string)
1727 :group 'python
1728 :safe 'stringp)
1729 1769
1730(defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ " 1770(defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ "
1731 "Regular expression matching pdb input prompt of Python shell. 1771 "Regular expression matching pdb input prompt of Python shell.
1732It should not contain a caret (^) at the beginning." 1772It should not contain a caret (^) at the beginning."
1733 :type 'string 1773 :type 'string)
1734 :group 'python
1735 :safe 'stringp)
1736 1774
1737(defcustom python-shell-enable-font-lock t 1775(defcustom python-shell-enable-font-lock t
1738 "Should syntax highlighting be enabled in the Python shell buffer? 1776 "Should syntax highlighting be enabled in the Python shell buffer?
@@ -1802,6 +1840,162 @@ virtualenv."
1802 :type '(alist string) 1840 :type '(alist string)
1803 :group 'python) 1841 :group 'python)
1804 1842
1843(defvar python-shell--prompt-calculated-input-regexp nil
1844 "Calculated input prompt regexp for inferior python shell.
1845Do not set this variable directly, instead use
1846`python-shell-prompt-set-calculated-regexps'.")
1847
1848(defvar python-shell--prompt-calculated-output-regexp nil
1849 "Calculated output prompt regexp for inferior python shell.
1850Do not set this variable directly, instead use
1851`python-shell-set-prompt-regexp'.")
1852
1853(defun python-shell-prompt-detect ()
1854 "Detect prompts for the current `python-shell-interpreter'.
1855When prompts can be retrieved successfully from the
1856`python-shell-interpreter' run with
1857`python-shell-interpreter-interactive-arg', returns a list of
1858three elements, where the first two are input prompts and the
1859last one is an output prompt. When no prompts can be detected
1860and `python-shell-prompt-detect-failure-warning' is non-nil,
1861shows a warning with instructions to avoid hangs and returns nil.
1862When `python-shell-prompt-detect-enabled' is nil avoids any
1863detection and just returns nil."
1864 (when python-shell-prompt-detect-enabled
1865 (let* ((process-environment (python-shell-calculate-process-environment))
1866 (exec-path (python-shell-calculate-exec-path))
1867 (python-code-file
1868 (python-shell--save-temp-file
1869 (concat
1870 "import sys\n"
1871 "ps = [getattr(sys, 'ps%s' % i, '') for i in range(1,4)]\n"
1872 ;; JSON is built manually for compatibility
1873 "ps_json = '\\n[\"%s\", \"%s\", \"%s\"]\\n' % tuple(ps)\n"
1874 "print (ps_json)\n"
1875 "sys.exit(0)\n")))
1876 (output
1877 (with-temp-buffer
1878 (call-process
1879 (executable-find python-shell-interpreter)
1880 python-code-file
1881 '(t nil)
1882 nil
1883 python-shell-interpreter-interactive-arg)
1884 (ignore-errors (delete-file python-code-file))
1885 (buffer-string)))
1886 (prompts
1887 (catch 'prompts
1888 (dolist (line (split-string output "\n" t))
1889 (let ((res
1890 ;; Check if current line is a valid JSON array
1891 (and (string= (substring line 0 2) "[\"")
1892 (ignore-errors
1893 ;; Return prompts as a list, not vector
1894 (append (json-read-from-string line) nil)))))
1895 ;; The list must contain 3 strings, where the first
1896 ;; is the input prompt, the second is the block
1897 ;; prompt and the last one is the output prompt. The
1898 ;; input prompt is the only one that can't be empty.
1899 (when (and (= (length res) 3)
1900 (cl-every #'stringp res)
1901 (not (string= (car res) "")))
1902 (throw 'prompts res))))
1903 nil)))
1904 (when (and (not prompts)
1905 python-shell-prompt-detect-failure-warning)
1906 (warn
1907 (concat
1908 "Python shell prompts cannot be detected.\n"
1909 "If your emacs session hangs when starting python shells\n"
1910 "recover with `keyboard-quit' and then try fixing the\n"
1911 "interactive flag for your interpreter by adjusting the\n"
1912 "`python-shell-interpreter-interactive-arg' or add regexps\n"
1913 "matching shell prompts in the directory-local friendly vars:\n"
1914 " + `python-shell-prompt-regexp'\n"
1915 " + `python-shell-prompt-block-regexp'\n"
1916 " + `python-shell-prompt-output-regexp'\n"
1917 "Or alternatively in:\n"
1918 " + `python-shell-prompt-input-regexps'\n"
1919 " + `python-shell-prompt-output-regexps'")))
1920 prompts)))
1921
1922(defun python-shell-prompt-validate-regexps ()
1923 "Validate all user provided regexps for prompts.
1924Signals `user-error' if any of these vars contain invalid
1925regexps: `python-shell-prompt-regexp',
1926`python-shell-prompt-block-regexp',
1927`python-shell-prompt-pdb-regexp',
1928`python-shell-prompt-output-regexp',
1929`python-shell-prompt-input-regexps',
1930`python-shell-prompt-output-regexps'."
1931 (dolist (symbol (list 'python-shell-prompt-input-regexps
1932 'python-shell-prompt-output-regexps
1933 'python-shell-prompt-regexp
1934 'python-shell-prompt-block-regexp
1935 'python-shell-prompt-pdb-regexp
1936 'python-shell-prompt-output-regexp))
1937 (dolist (regexp (let ((regexps (symbol-value symbol)))
1938 (if (listp regexps)
1939 regexps
1940 (list regexps))))
1941 (when (not (python-util-valid-regexp-p regexp))
1942 (user-error "Invalid regexp %s in `%s'"
1943 regexp symbol)))))
1944
1945(defun python-shell-prompt-set-calculated-regexps ()
1946 "Detect and set input and output prompt regexps.
1947Build and set the values for `python-shell-input-prompt-regexp'
1948and `python-shell-output-prompt-regexp' using the values from
1949`python-shell-prompt-regexp', `python-shell-prompt-block-regexp',
1950`python-shell-prompt-pdb-regexp',
1951`python-shell-prompt-output-regexp',
1952`python-shell-prompt-input-regexps',
1953`python-shell-prompt-output-regexps' and detected prompts from
1954`python-shell-prompt-detect'."
1955 (when (not (and python-shell--prompt-calculated-input-regexp
1956 python-shell--prompt-calculated-output-regexp))
1957 (let* ((detected-prompts (python-shell-prompt-detect))
1958 (input-prompts nil)
1959 (output-prompts nil)
1960 (build-regexp
1961 (lambda (prompts)
1962 (concat "^\\("
1963 (mapconcat #'identity
1964 (sort prompts
1965 (lambda (a b)
1966 (let ((length-a (length a))
1967 (length-b (length b)))
1968 (if (= length-a length-b)
1969 (string< a b)
1970 (> (length a) (length b))))))
1971 "\\|")
1972 "\\)"))))
1973 ;; Validate ALL regexps
1974 (python-shell-prompt-validate-regexps)
1975 ;; Collect all user defined input prompts
1976 (dolist (prompt (append python-shell-prompt-input-regexps
1977 (list python-shell-prompt-regexp
1978 python-shell-prompt-block-regexp
1979 python-shell-prompt-pdb-regexp)))
1980 (cl-pushnew prompt input-prompts :test #'string=))
1981 ;; Collect all user defined output prompts
1982 (dolist (prompt (cons python-shell-prompt-output-regexp
1983 python-shell-prompt-output-regexps))
1984 (cl-pushnew prompt output-prompts :test #'string=))
1985 ;; Collect detected prompts if any
1986 (when detected-prompts
1987 (dolist (prompt (butlast detected-prompts))
1988 (setq prompt (regexp-quote prompt))
1989 (cl-pushnew prompt input-prompts :test #'string=))
1990 (cl-pushnew (regexp-quote
1991 (car (last detected-prompts)))
1992 output-prompts :test #'string=))
1993 ;; Set input and output prompt regexps from collected prompts
1994 (setq python-shell--prompt-calculated-input-regexp
1995 (funcall build-regexp input-prompts)
1996 python-shell--prompt-calculated-output-regexp
1997 (funcall build-regexp output-prompts)))))
1998
1805(defun python-shell-get-process-name (dedicated) 1999(defun python-shell-get-process-name (dedicated)
1806 "Calculate the appropriate process name for inferior Python process. 2000 "Calculate the appropriate process name for inferior Python process.
1807If DEDICATED is t and the variable `buffer-file-name' is non-nil 2001If DEDICATED is t and the variable `buffer-file-name' is non-nil
@@ -1824,10 +2018,10 @@ uniqueness for different types of configurations."
1824 python-shell-internal-buffer-name 2018 python-shell-internal-buffer-name
1825 (md5 2019 (md5
1826 (concat 2020 (concat
1827 (python-shell-parse-command) 2021 python-shell-interpreter
1828 python-shell-prompt-regexp 2022 python-shell-interpreter-args
1829 python-shell-prompt-block-regexp 2023 python-shell--prompt-calculated-input-regexp
1830 python-shell-prompt-output-regexp 2024 python-shell--prompt-calculated-output-regexp
1831 (mapconcat #'symbol-value python-shell-setup-codes "") 2025 (mapconcat #'symbol-value python-shell-setup-codes "")
1832 (mapconcat #'identity python-shell-process-environment "") 2026 (mapconcat #'identity python-shell-process-environment "")
1833 (mapconcat #'identity python-shell-extra-pythonpaths "") 2027 (mapconcat #'identity python-shell-extra-pythonpaths "")
@@ -1921,12 +2115,19 @@ initialization of the interpreter via `python-shell-setup-codes'
1921variable. 2115variable.
1922 2116
1923\(Type \\[describe-mode] in the process buffer for a list of commands.)" 2117\(Type \\[describe-mode] in the process buffer for a list of commands.)"
1924 (and python-shell--parent-buffer 2118 (let ((interpreter python-shell-interpreter)
1925 (python-util-clone-local-variables python-shell--parent-buffer)) 2119 (args python-shell-interpreter-args))
1926 (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" 2120 (when python-shell--parent-buffer
1927 python-shell-prompt-regexp 2121 (python-util-clone-local-variables python-shell--parent-buffer))
1928 python-shell-prompt-block-regexp 2122 ;; Users can override default values for these vars when calling
1929 python-shell-prompt-pdb-regexp)) 2123 ;; `run-python'. This ensures new values let-bound in
2124 ;; `python-shell-make-comint' are locally set.
2125 (set (make-local-variable 'python-shell-interpreter) interpreter)
2126 (set (make-local-variable 'python-shell-interpreter-args) args))
2127 (set (make-local-variable 'python-shell--prompt-calculated-input-regexp) nil)
2128 (set (make-local-variable 'python-shell--prompt-calculated-output-regexp) nil)
2129 (python-shell-prompt-set-calculated-regexps)
2130 (setq comint-prompt-regexp python-shell--prompt-calculated-input-regexp)
1930 (setq mode-line-process '(":%s")) 2131 (setq mode-line-process '(":%s"))
1931 (make-local-variable 'comint-output-filter-functions) 2132 (make-local-variable 'comint-output-filter-functions)
1932 (add-hook 'comint-output-filter-functions 2133 (add-hook 'comint-output-filter-functions
@@ -1989,10 +2190,20 @@ killed."
1989 (exec-path (python-shell-calculate-exec-path))) 2190 (exec-path (python-shell-calculate-exec-path)))
1990 (when (not (comint-check-proc proc-buffer-name)) 2191 (when (not (comint-check-proc proc-buffer-name))
1991 (let* ((cmdlist (split-string-and-unquote cmd)) 2192 (let* ((cmdlist (split-string-and-unquote cmd))
2193 (interpreter (car cmdlist))
2194 (args (cdr cmdlist))
1992 (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name 2195 (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name
1993 (car cmdlist) nil (cdr cmdlist))) 2196 interpreter nil args))
1994 (python-shell--parent-buffer (current-buffer)) 2197 (python-shell--parent-buffer (current-buffer))
1995 (process (get-buffer-process buffer))) 2198 (process (get-buffer-process buffer))
2199 ;; As the user may have overriden default values for
2200 ;; these vars on `run-python', let-binding them allows
2201 ;; to have the new right values in all setup code
2202 ;; that's is done in `inferior-python-mode', which is
2203 ;; important, especially for prompt detection.
2204 (python-shell-interpreter interpreter)
2205 (python-shell-interpreter-args
2206 (mapconcat #'identity args " ")))
1996 (with-current-buffer buffer 2207 (with-current-buffer buffer
1997 (inferior-python-mode)) 2208 (inferior-python-mode))
1998 (accept-process-output process) 2209 (accept-process-output process)
@@ -2064,8 +2275,12 @@ startup."
2064 "Return inferior Python process for current buffer." 2275 "Return inferior Python process for current buffer."
2065 (get-buffer-process (python-shell-get-buffer))) 2276 (get-buffer-process (python-shell-get-buffer)))
2066 2277
2067(defun python-shell-get-or-create-process () 2278(defun python-shell-get-or-create-process (&optional cmd dedicated show)
2068 "Get or create an inferior Python process for current buffer and return it." 2279 "Get or create an inferior Python process for current buffer and return it.
2280Arguments CMD, DEDICATED and SHOW are those of `run-python' and
2281are used to start the shell. If those arguments are not
2282provided, `run-python' is called interactively and the user will
2283be asked for their values."
2069 (let* ((dedicated-proc-name (python-shell-get-process-name t)) 2284 (let* ((dedicated-proc-name (python-shell-get-process-name t))
2070 (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name)) 2285 (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name))
2071 (global-proc-name (python-shell-get-process-name nil)) 2286 (global-proc-name (python-shell-get-process-name nil))
@@ -2074,7 +2289,11 @@ startup."
2074 (global-running (comint-check-proc global-proc-buffer-name)) 2289 (global-running (comint-check-proc global-proc-buffer-name))
2075 (current-prefix-arg 16)) 2290 (current-prefix-arg 16))
2076 (when (and (not dedicated-running) (not global-running)) 2291 (when (and (not dedicated-running) (not global-running))
2077 (if (call-interactively 'run-python) 2292 (if (if (not cmd)
2293 ;; XXX: Refactor code such that calling `run-python'
2294 ;; interactively is not needed anymore.
2295 (call-interactively 'run-python)
2296 (run-python cmd dedicated show))
2078 (setq dedicated-running t) 2297 (setq dedicated-running t)
2079 (setq global-running t))) 2298 (setq global-running t)))
2080 ;; Always prefer dedicated 2299 ;; Always prefer dedicated
@@ -2157,10 +2376,13 @@ detecting a prompt at the end of the buffer."
2157 (when (string-match 2376 (when (string-match
2158 ;; XXX: It seems on OSX an extra carriage return is attached 2377 ;; XXX: It seems on OSX an extra carriage return is attached
2159 ;; at the end of output, this handles that too. 2378 ;; at the end of output, this handles that too.
2160 (format "\r?\n\\(?:%s\\|%s\\|%s\\)$" 2379 (concat
2161 python-shell-prompt-regexp 2380 "\r?\n"
2162 python-shell-prompt-block-regexp 2381 ;; Remove initial caret from calculated regexp
2163 python-shell-prompt-pdb-regexp) 2382 (replace-regexp-in-string
2383 (rx string-start ?^) ""
2384 python-shell--prompt-calculated-input-regexp)
2385 "$")
2164 python-shell-output-filter-buffer) 2386 python-shell-output-filter-buffer)
2165 ;; Output ends when `python-shell-output-filter-buffer' contains 2387 ;; Output ends when `python-shell-output-filter-buffer' contains
2166 ;; the prompt attached at the end of it. 2388 ;; the prompt attached at the end of it.
@@ -2168,9 +2390,9 @@ detecting a prompt at the end of the buffer."
2168 python-shell-output-filter-buffer 2390 python-shell-output-filter-buffer
2169 (substring python-shell-output-filter-buffer 2391 (substring python-shell-output-filter-buffer
2170 0 (match-beginning 0))) 2392 0 (match-beginning 0)))
2171 (when (and (> (length python-shell-prompt-output-regexp) 0) 2393 (when (string-match
2172 (string-match (concat "^" python-shell-prompt-output-regexp) 2394 python-shell--prompt-calculated-output-regexp
2173 python-shell-output-filter-buffer)) 2395 python-shell-output-filter-buffer)
2174 ;; Some shells, like iPython might append a prompt before the 2396 ;; Some shells, like iPython might append a prompt before the
2175 ;; output, clean that. 2397 ;; output, clean that.
2176 (setq python-shell-output-filter-buffer 2398 (setq python-shell-output-filter-buffer
@@ -2456,11 +2678,11 @@ LINE is used to detect the context on how to complete given INPUT."
2456 ((and (> 2678 ((and (>
2457 (length python-shell-completion-module-string-code) 0) 2679 (length python-shell-completion-module-string-code) 0)
2458 (string-match 2680 (string-match
2459 (concat "^" python-shell-prompt-regexp) prompt) 2681 python-shell--prompt-calculated-input-regexp prompt)
2460 (string-match "^[ \t]*\\(from\\|import\\)[ \t]" line)) 2682 (string-match "^[ \t]*\\(from\\|import\\)[ \t]" line))
2461 'import) 2683 'import)
2462 ((string-match 2684 ((string-match
2463 (concat "^" python-shell-prompt-regexp) prompt) 2685 python-shell--prompt-calculated-input-regexp prompt)
2464 'default) 2686 'default)
2465 (t nil))) 2687 (t nil)))
2466 (completion-code 2688 (completion-code
@@ -3706,6 +3928,10 @@ returned as is."
3706 "" 3928 ""
3707 string)) 3929 string))
3708 3930
3931(defun python-util-valid-regexp-p (regexp)
3932 "Return non-nil if REGEXP is valid."
3933 (ignore-errors (string-match regexp "") t))
3934
3709 3935
3710(defun python-electric-pair-string-delimiter () 3936(defun python-electric-pair-string-delimiter ()
3711 (when (and electric-pair-mode 3937 (when (and electric-pair-mode
diff --git a/test/ChangeLog b/test/ChangeLog
index cf4ddc83544..b4b3bedcbdc 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,34 @@
12014-07-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
2
3 * automated/python-tests.el (python-shell-make-comint-1):
4 (python-shell-make-comint-2): Fix indentation.
5 (python-shell-make-comint-3)
6 (python-shell-make-comint-4): New tests.
7 (python-shell-get-or-create-process-1): Fix test.
8 (python-shell-get-or-create-process-2)
9 (python-shell-get-or-create-process-3): New tests.
10 (python-shell-internal-get-or-create-process-1): Fix test.
11 (python-shell-prompt-detect-1): New test.
12 (python-shell-prompt-detect-2): New test. (Bug#17370)
13 (python-shell-prompt-detect-3)
14 (python-shell-prompt-detect-4)
15 (python-shell-prompt-detect-5)
16 (python-shell-prompt-detect-6)
17 (python-shell-prompt-validate-regexps-1)
18 (python-shell-prompt-validate-regexps-2)
19 (python-shell-prompt-validate-regexps-3)
20 (python-shell-prompt-validate-regexps-4)
21 (python-shell-prompt-validate-regexps-5)
22 (python-shell-prompt-validate-regexps-6)
23 (python-shell-prompt-validate-regexps-7)
24 (python-shell-prompt-set-calculated-regexps-1)
25 (python-shell-prompt-set-calculated-regexps-2)
26 (python-shell-prompt-set-calculated-regexps-3)
27 (python-shell-prompt-set-calculated-regexps-4)
28 (python-shell-prompt-set-calculated-regexps-5)
29 (python-shell-prompt-set-calculated-regexps-6)
30 (python-util-valid-regexp-p-1): New tests.
31
12014-07-09 Fabián Ezequiel Gallina <fgallina@gnu.org> 322014-07-09 Fabián Ezequiel Gallina <fgallina@gnu.org>
2 33
3 * automated/python-tests.el 34 * automated/python-tests.el
@@ -34,13 +65,12 @@
34 (python-info-dedenter-statement-p-4) 65 (python-info-dedenter-statement-p-4)
35 (python-info-dedenter-statement-p-5): New tests. 66 (python-info-dedenter-statement-p-5): New tests.
36 67
37
382014-07-01 Fabián Ezequiel Gallina <fgallina@gnu.org> 682014-07-01 Fabián Ezequiel Gallina <fgallina@gnu.org>
39 69
40 * automated/python-tests.el 70 * automated/python-tests.el
41 (python-tests-self-insert): New function. 71 (python-tests-self-insert): New function.
42 (python-triple-quote-pairing): Use it. 72 (python-triple-quote-pairing): Use it.
43 (python-util-forward-comment-1): New test. (Bug#17658) 73 (python-parens-electric-indent-1): New test. (Bug#17658)
44 74
452014-06-28 Leo Liu <sdl.web@gmail.com> 752014-06-28 Leo Liu <sdl.web@gmail.com>
46 76
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el
index 3a4eda36bfe..a60da31e44c 100644
--- a/test/automated/python-tests.el
+++ b/test/automated/python-tests.el
@@ -1773,8 +1773,8 @@ Using `python-shell-interpreter' and
1773 (proc-name (python-shell-get-process-name nil)) 1773 (proc-name (python-shell-get-process-name nil))
1774 (shell-buffer 1774 (shell-buffer
1775 (python-tests-with-temp-buffer 1775 (python-tests-with-temp-buffer
1776 "" (python-shell-make-comint 1776 "" (python-shell-make-comint
1777 (python-shell-parse-command) proc-name))) 1777 (python-shell-parse-command) proc-name)))
1778 (process (get-buffer-process shell-buffer))) 1778 (process (get-buffer-process shell-buffer)))
1779 (unwind-protect 1779 (unwind-protect
1780 (progn 1780 (progn
@@ -1794,8 +1794,8 @@ Using `python-shell-interpreter' and
1794 (proc-name (python-shell-internal-get-process-name)) 1794 (proc-name (python-shell-internal-get-process-name))
1795 (shell-buffer 1795 (shell-buffer
1796 (python-tests-with-temp-buffer 1796 (python-tests-with-temp-buffer
1797 "" (python-shell-make-comint 1797 "" (python-shell-make-comint
1798 (python-shell-parse-command) proc-name nil t))) 1798 (python-shell-parse-command) proc-name nil t)))
1799 (process (get-buffer-process shell-buffer))) 1799 (process (get-buffer-process shell-buffer)))
1800 (unwind-protect 1800 (unwind-protect
1801 (progn 1801 (progn
@@ -1806,6 +1806,79 @@ Using `python-shell-interpreter' and
1806 (should (string= (buffer-name) (format " *%s*" proc-name))))) 1806 (should (string= (buffer-name) (format " *%s*" proc-name)))))
1807 (kill-buffer shell-buffer)))) 1807 (kill-buffer shell-buffer))))
1808 1808
1809(ert-deftest python-shell-make-comint-3 ()
1810 "Check comint creation with overriden python interpreter and args.
1811The command passed to `python-shell-make-comint' as argument must
1812locally override global values set in `python-shell-interpreter'
1813and `python-shell-interpreter-args' in the new shell buffer."
1814 (skip-unless (executable-find python-tests-shell-interpreter))
1815 (let* ((python-shell-setup-codes nil)
1816 (python-shell-interpreter "interpreter")
1817 (python-shell-interpreter-args "--some-args")
1818 (proc-name (python-shell-get-process-name nil))
1819 (interpreter-override
1820 (concat (executable-find python-tests-shell-interpreter) " " "-i"))
1821 (shell-buffer
1822 (python-tests-with-temp-buffer
1823 "" (python-shell-make-comint interpreter-override proc-name nil)))
1824 (process (get-buffer-process shell-buffer)))
1825 (unwind-protect
1826 (progn
1827 (set-process-query-on-exit-flag process nil)
1828 (should (process-live-p process))
1829 (with-current-buffer shell-buffer
1830 (should (eq major-mode 'inferior-python-mode))
1831 (should (string= python-shell-interpreter
1832 (executable-find python-tests-shell-interpreter)))
1833 (should (string= python-shell-interpreter-args "-i"))))
1834 (kill-buffer shell-buffer))))
1835
1836(ert-deftest python-shell-make-comint-4 ()
1837 "Check shell calculated prompts regexps are set."
1838 (skip-unless (executable-find python-tests-shell-interpreter))
1839 (let* ((process-environment process-environment)
1840 (python-shell-setup-codes nil)
1841 (python-shell-interpreter
1842 (executable-find python-tests-shell-interpreter))
1843 (python-shell-interpreter-args "-i")
1844 (python-shell--prompt-calculated-input-regexp nil)
1845 (python-shell--prompt-calculated-output-regexp nil)
1846 (python-shell-prompt-detect-enabled t)
1847 (python-shell-prompt-input-regexps '("extralargeinputprompt" "sml"))
1848 (python-shell-prompt-output-regexps '("extralargeoutputprompt" "sml"))
1849 (python-shell-prompt-regexp "in")
1850 (python-shell-prompt-block-regexp "block")
1851 (python-shell-prompt-pdb-regexp "pdf")
1852 (python-shell-prompt-output-regexp "output")
1853 (startup-code (concat "import sys\n"
1854 "sys.ps1 = 'py> '\n"
1855 "sys.ps2 = '..> '\n"
1856 "sys.ps3 = 'out '\n"))
1857 (startup-file (python-shell--save-temp-file startup-code))
1858 (proc-name (python-shell-get-process-name nil))
1859 (shell-buffer
1860 (progn
1861 (setenv "PYTHONSTARTUP" startup-file)
1862 (python-tests-with-temp-buffer
1863 "" (python-shell-make-comint
1864 (python-shell-parse-command) proc-name nil))))
1865 (process (get-buffer-process shell-buffer)))
1866 (unwind-protect
1867 (progn
1868 (set-process-query-on-exit-flag process nil)
1869 (should (process-live-p process))
1870 (with-current-buffer shell-buffer
1871 (should (eq major-mode 'inferior-python-mode))
1872 (should (string=
1873 python-shell--prompt-calculated-input-regexp
1874 (concat "^\\(extralargeinputprompt\\|\\.\\.> \\|"
1875 "block\\|py> \\|pdf\\|sml\\|in\\)")))
1876 (should (string=
1877 python-shell--prompt-calculated-output-regexp
1878 "^\\(extralargeoutputprompt\\|output\\|out \\|sml\\)"))))
1879 (delete-file startup-file)
1880 (kill-buffer shell-buffer))))
1881
1809(ert-deftest python-shell-get-process-1 () 1882(ert-deftest python-shell-get-process-1 ()
1810 "Check dedicated shell process preference over global." 1883 "Check dedicated shell process preference over global."
1811 (skip-unless (executable-find python-tests-shell-interpreter)) 1884 (skip-unless (executable-find python-tests-shell-interpreter))
@@ -1840,54 +1913,370 @@ Using `python-shell-interpreter' and
1840 (ignore-errors (kill-buffer dedicated-shell-buffer)))))) 1913 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
1841 1914
1842(ert-deftest python-shell-get-or-create-process-1 () 1915(ert-deftest python-shell-get-or-create-process-1 ()
1843 "Check shell process creation fallback." 1916 "Check shell dedicated process creation."
1844 :expected-result :failed 1917 (skip-unless (executable-find python-tests-shell-interpreter))
1845 (python-tests-with-temp-file 1918 (python-tests-with-temp-file
1846 "" 1919 ""
1847 ;; XXX: Break early until we can skip stuff. We need to mimic 1920 (let* ((python-shell-interpreter
1848 ;; user interaction because `python-shell-get-or-create-process' 1921 (executable-find python-tests-shell-interpreter))
1849 ;; asks for all arguments interactively when a shell process 1922 (use-dialog-box)
1850 ;; doesn't exist. 1923 (dedicated-process-name (python-shell-get-process-name t))
1851 (should nil) 1924 (dedicated-process
1852 (let* ((python-shell-interpreter 1925 (python-shell-get-or-create-process python-shell-interpreter t))
1853 (executable-find python-tests-shell-interpreter)) 1926 (dedicated-shell-buffer (process-buffer dedicated-process)))
1854 (use-dialog-box) 1927 (unwind-protect
1855 (dedicated-process-name (python-shell-get-process-name t)) 1928 (progn
1856 (dedicated-process (python-shell-get-or-create-process)) 1929 (set-process-query-on-exit-flag dedicated-process nil)
1857 (dedicated-shell-buffer (process-buffer dedicated-process))) 1930 ;; should be dedicated.
1858 (unwind-protect 1931 (should (equal (process-name dedicated-process)
1859 (progn 1932 dedicated-process-name))
1860 (set-process-query-on-exit-flag dedicated-process nil) 1933 (kill-buffer dedicated-shell-buffer)
1861 ;; Prefer dedicated if not buffer exist. 1934 ;; Check there are no processes for current buffer.
1862 (should (equal (process-name dedicated-process) 1935 (should (not (python-shell-get-process))))
1863 dedicated-process-name)) 1936 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
1864 (kill-buffer dedicated-shell-buffer) 1937
1865 ;; No buffer available. 1938(ert-deftest python-shell-get-or-create-process-2 ()
1866 (should (not (python-shell-get-process)))) 1939 "Check shell global process creation."
1867 (ignore-errors (kill-buffer dedicated-shell-buffer)))))) 1940 (skip-unless (executable-find python-tests-shell-interpreter))
1941 (python-tests-with-temp-file
1942 ""
1943 (let* ((python-shell-interpreter
1944 (executable-find python-tests-shell-interpreter))
1945 (use-dialog-box)
1946 (process-name (python-shell-get-process-name nil))
1947 (process
1948 (python-shell-get-or-create-process python-shell-interpreter))
1949 (shell-buffer (process-buffer process)))
1950 (unwind-protect
1951 (progn
1952 (set-process-query-on-exit-flag process nil)
1953 ;; should be global.
1954 (should (equal (process-name process) process-name))
1955 (kill-buffer shell-buffer)
1956 ;; Check there are no processes for current buffer.
1957 (should (not (python-shell-get-process))))
1958 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
1959
1960(ert-deftest python-shell-get-or-create-process-3 ()
1961 "Check shell dedicated/global process preference."
1962 (skip-unless (executable-find python-tests-shell-interpreter))
1963 (python-tests-with-temp-file
1964 ""
1965 (let* ((python-shell-interpreter
1966 (executable-find python-tests-shell-interpreter))
1967 (use-dialog-box)
1968 (dedicated-process-name (python-shell-get-process-name t))
1969 (global-process)
1970 (dedicated-process))
1971 (unwind-protect
1972 (progn
1973 ;; Create global process
1974 (run-python python-shell-interpreter nil)
1975 (setq global-process (get-buffer-process "*Python*"))
1976 (should global-process)
1977 (set-process-query-on-exit-flag global-process nil)
1978 ;; Create dedicated process
1979 (run-python python-shell-interpreter t)
1980 (setq dedicated-process (get-process dedicated-process-name))
1981 (should dedicated-process)
1982 (set-process-query-on-exit-flag dedicated-process nil)
1983 ;; Prefer dedicated.
1984 (should (equal (python-shell-get-or-create-process)
1985 dedicated-process))
1986 ;; Kill the dedicated so the global takes over.
1987 (kill-buffer (process-buffer dedicated-process))
1988 ;; Detect global.
1989 (should (equal (python-shell-get-or-create-process) global-process))
1990 ;; Kill the global.
1991 (kill-buffer (process-buffer global-process))
1992 ;; Check there are no processes for current buffer.
1993 (should (not (python-shell-get-process))))
1994 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
1868 1995
1869(ert-deftest python-shell-internal-get-or-create-process-1 () 1996(ert-deftest python-shell-internal-get-or-create-process-1 ()
1870 "Check internal shell process creation fallback." 1997 "Check internal shell process creation fallback."
1871 (skip-unless (executable-find python-tests-shell-interpreter)) 1998 (skip-unless (executable-find python-tests-shell-interpreter))
1872 (python-tests-with-temp-file 1999 (python-tests-with-temp-file
1873 "" 2000 ""
1874 (should (not (process-live-p (python-shell-internal-get-process-name)))) 2001 (should (not (process-live-p (python-shell-internal-get-process-name))))
1875 (let* ((python-shell-interpreter 2002 (let* ((python-shell-interpreter
1876 (executable-find python-tests-shell-interpreter)) 2003 (executable-find python-tests-shell-interpreter))
1877 (internal-process-name (python-shell-internal-get-process-name)) 2004 (internal-process-name (python-shell-internal-get-process-name))
1878 (internal-process (python-shell-internal-get-or-create-process)) 2005 (internal-process (python-shell-internal-get-or-create-process))
1879 (internal-shell-buffer (process-buffer internal-process))) 2006 (internal-shell-buffer (process-buffer internal-process)))
1880 (unwind-protect 2007 (unwind-protect
1881 (progn 2008 (progn
1882 (set-process-query-on-exit-flag internal-process nil) 2009 (set-process-query-on-exit-flag internal-process nil)
1883 (should (equal (process-name internal-process) 2010 (should (equal (process-name internal-process)
1884 internal-process-name)) 2011 internal-process-name))
1885 (should (equal internal-process 2012 (should (equal internal-process
1886 (python-shell-internal-get-or-create-process))) 2013 (python-shell-internal-get-or-create-process)))
1887 ;; No user buffer available. 2014 ;; Assert the internal process is not a user process
1888 (should (not (python-shell-get-process))) 2015 (should (not (python-shell-get-process)))
1889 (kill-buffer internal-shell-buffer)) 2016 (kill-buffer internal-shell-buffer))
1890 (ignore-errors (kill-buffer internal-shell-buffer)))))) 2017 (ignore-errors (kill-buffer internal-shell-buffer))))))
2018
2019(ert-deftest python-shell-prompt-detect-1 ()
2020 "Check prompt autodetection."
2021 (skip-unless (executable-find python-tests-shell-interpreter))
2022 (let ((process-environment process-environment))
2023 ;; Ensure no startup file is enabled
2024 (setenv "PYTHONSTARTUP" "")
2025 (should python-shell-prompt-detect-enabled)
2026 (should (equal (python-shell-prompt-detect) '(">>> " "... " "")))))
2027
2028(ert-deftest python-shell-prompt-detect-2 ()
2029 "Check prompt autodetection with startup file. Bug#17370."
2030 (skip-unless (executable-find python-tests-shell-interpreter))
2031 (let* ((process-environment process-environment)
2032 (startup-code (concat "import sys\n"
2033 "sys.ps1 = 'py> '\n"
2034 "sys.ps2 = '..> '\n"
2035 "sys.ps3 = 'out '\n"))
2036 (startup-file (python-shell--save-temp-file startup-code)))
2037 (unwind-protect
2038 (progn
2039 ;; Ensure startup file is enabled
2040 (setenv "PYTHONSTARTUP" startup-file)
2041 (should python-shell-prompt-detect-enabled)
2042 (should (equal (python-shell-prompt-detect) '("py> " "..> " "out "))))
2043 (ignore-errors (delete-file startup-file)))))
2044
2045(ert-deftest python-shell-prompt-detect-3 ()
2046 "Check prompts are not autodetected when feature is disabled."
2047 (skip-unless (executable-find python-tests-shell-interpreter))
2048 (let ((process-environment process-environment)
2049 (python-shell-prompt-detect-enabled nil))
2050 ;; Ensure no startup file is enabled
2051 (should (not python-shell-prompt-detect-enabled))
2052 (should (not (python-shell-prompt-detect)))))
2053
2054(ert-deftest python-shell-prompt-detect-4 ()
2055 "Check warning is shown when detection fails."
2056 (skip-unless (executable-find python-tests-shell-interpreter))
2057 (let* ((process-environment process-environment)
2058 ;; Trigger failure by removing prompts in the startup file
2059 (startup-code (concat "import sys\n"
2060 "sys.ps1 = ''\n"
2061 "sys.ps2 = ''\n"
2062 "sys.ps3 = ''\n"))
2063 (startup-file (python-shell--save-temp-file startup-code)))
2064 (unwind-protect
2065 (progn
2066 (kill-buffer (get-buffer-create "*Warnings*"))
2067 (should (not (get-buffer "*Warnings*")))
2068 (setenv "PYTHONSTARTUP" startup-file)
2069 (should python-shell-prompt-detect-failure-warning)
2070 (should python-shell-prompt-detect-enabled)
2071 (should (not (python-shell-prompt-detect)))
2072 (should (get-buffer "*Warnings*")))
2073 (ignore-errors (delete-file startup-file)))))
2074
2075(ert-deftest python-shell-prompt-detect-5 ()
2076 "Check disabled warnings are not shown when detection fails."
2077 (skip-unless (executable-find python-tests-shell-interpreter))
2078 (let* ((process-environment process-environment)
2079 (startup-code (concat "import sys\n"
2080 "sys.ps1 = ''\n"
2081 "sys.ps2 = ''\n"
2082 "sys.ps3 = ''\n"))
2083 (startup-file (python-shell--save-temp-file startup-code))
2084 (python-shell-prompt-detect-failure-warning nil))
2085 (unwind-protect
2086 (progn
2087 (kill-buffer (get-buffer-create "*Warnings*"))
2088 (should (not (get-buffer "*Warnings*")))
2089 (setenv "PYTHONSTARTUP" startup-file)
2090 (should (not python-shell-prompt-detect-failure-warning))
2091 (should python-shell-prompt-detect-enabled)
2092 (should (not (python-shell-prompt-detect)))
2093 (should (not (get-buffer "*Warnings*"))))
2094 (ignore-errors (delete-file startup-file)))))
2095
2096(ert-deftest python-shell-prompt-detect-6 ()
2097 "Warnings are not shown when detection is disabled."
2098 (skip-unless (executable-find python-tests-shell-interpreter))
2099 (let* ((process-environment process-environment)
2100 (startup-code (concat "import sys\n"
2101 "sys.ps1 = ''\n"
2102 "sys.ps2 = ''\n"
2103 "sys.ps3 = ''\n"))
2104 (startup-file (python-shell--save-temp-file startup-code))
2105 (python-shell-prompt-detect-failure-warning t)
2106 (python-shell-prompt-detect-enabled nil))
2107 (unwind-protect
2108 (progn
2109 (kill-buffer (get-buffer-create "*Warnings*"))
2110 (should (not (get-buffer "*Warnings*")))
2111 (setenv "PYTHONSTARTUP" startup-file)
2112 (should python-shell-prompt-detect-failure-warning)
2113 (should (not python-shell-prompt-detect-enabled))
2114 (should (not (python-shell-prompt-detect)))
2115 (should (not (get-buffer "*Warnings*"))))
2116 (ignore-errors (delete-file startup-file)))))
2117
2118(ert-deftest python-shell-prompt-validate-regexps-1 ()
2119 "Check `python-shell-prompt-input-regexps' are validated."
2120 (let* ((python-shell-prompt-input-regexps '("\\("))
2121 (error-data (should-error (python-shell-prompt-validate-regexps)
2122 :type 'user-error)))
2123 (should
2124 (string= (cadr error-data)
2125 "Invalid regexp \\( in `python-shell-prompt-input-regexps'"))))
2126
2127(ert-deftest python-shell-prompt-validate-regexps-2 ()
2128 "Check `python-shell-prompt-output-regexps' are validated."
2129 (let* ((python-shell-prompt-output-regexps '("\\("))
2130 (error-data (should-error (python-shell-prompt-validate-regexps)
2131 :type 'user-error)))
2132 (should
2133 (string= (cadr error-data)
2134 "Invalid regexp \\( in `python-shell-prompt-output-regexps'"))))
2135
2136(ert-deftest python-shell-prompt-validate-regexps-3 ()
2137 "Check `python-shell-prompt-regexp' is validated."
2138 (let* ((python-shell-prompt-regexp "\\(")
2139 (error-data (should-error (python-shell-prompt-validate-regexps)
2140 :type 'user-error)))
2141 (should
2142 (string= (cadr error-data)
2143 "Invalid regexp \\( in `python-shell-prompt-regexp'"))))
2144
2145(ert-deftest python-shell-prompt-validate-regexps-4 ()
2146 "Check `python-shell-prompt-block-regexp' is validated."
2147 (let* ((python-shell-prompt-block-regexp "\\(")
2148 (error-data (should-error (python-shell-prompt-validate-regexps)
2149 :type 'user-error)))
2150 (should
2151 (string= (cadr error-data)
2152 "Invalid regexp \\( in `python-shell-prompt-block-regexp'"))))
2153
2154(ert-deftest python-shell-prompt-validate-regexps-5 ()
2155 "Check `python-shell-prompt-pdb-regexp' is validated."
2156 (let* ((python-shell-prompt-pdb-regexp "\\(")
2157 (error-data (should-error (python-shell-prompt-validate-regexps)
2158 :type 'user-error)))
2159 (should
2160 (string= (cadr error-data)
2161 "Invalid regexp \\( in `python-shell-prompt-pdb-regexp'"))))
2162
2163(ert-deftest python-shell-prompt-validate-regexps-6 ()
2164 "Check `python-shell-prompt-output-regexp' is validated."
2165 (let* ((python-shell-prompt-output-regexp "\\(")
2166 (error-data (should-error (python-shell-prompt-validate-regexps)
2167 :type 'user-error)))
2168 (should
2169 (string= (cadr error-data)
2170 "Invalid regexp \\( in `python-shell-prompt-output-regexp'"))))
2171
2172(ert-deftest python-shell-prompt-validate-regexps-7 ()
2173 "Check default regexps are valid."
2174 ;; should not signal error
2175 (python-shell-prompt-validate-regexps))
2176
2177(ert-deftest python-shell-prompt-set-calculated-regexps-1 ()
2178 "Check regexps are validated."
2179 (let* ((python-shell-prompt-output-regexp '("\\("))
2180 (python-shell--prompt-calculated-input-regexp nil)
2181 (python-shell--prompt-calculated-output-regexp nil)
2182 (python-shell-prompt-detect-enabled nil)
2183 (error-data (should-error (python-shell-prompt-set-calculated-regexps)
2184 :type 'user-error)))
2185 (should
2186 (string= (cadr error-data)
2187 "Invalid regexp \\( in `python-shell-prompt-output-regexp'"))))
2188
2189(ert-deftest python-shell-prompt-set-calculated-regexps-2 ()
2190 "Check `python-shell-prompt-input-regexps' are set."
2191 (let* ((python-shell-prompt-input-regexps '("my" "prompt"))
2192 (python-shell-prompt-output-regexps '(""))
2193 (python-shell-prompt-regexp "")
2194 (python-shell-prompt-block-regexp "")
2195 (python-shell-prompt-pdb-regexp "")
2196 (python-shell-prompt-output-regexp "")
2197 (python-shell--prompt-calculated-input-regexp nil)
2198 (python-shell--prompt-calculated-output-regexp nil)
2199 (python-shell-prompt-detect-enabled nil))
2200 (python-shell-prompt-set-calculated-regexps)
2201 (should (string= python-shell--prompt-calculated-input-regexp
2202 "^\\(prompt\\|my\\|\\)"))))
2203
2204(ert-deftest python-shell-prompt-set-calculated-regexps-3 ()
2205 "Check `python-shell-prompt-output-regexps' are set."
2206 (let* ((python-shell-prompt-input-regexps '(""))
2207 (python-shell-prompt-output-regexps '("my" "prompt"))
2208 (python-shell-prompt-regexp "")
2209 (python-shell-prompt-block-regexp "")
2210 (python-shell-prompt-pdb-regexp "")
2211 (python-shell-prompt-output-regexp "")
2212 (python-shell--prompt-calculated-input-regexp nil)
2213 (python-shell--prompt-calculated-output-regexp nil)
2214 (python-shell-prompt-detect-enabled nil))
2215 (python-shell-prompt-set-calculated-regexps)
2216 (should (string= python-shell--prompt-calculated-output-regexp
2217 "^\\(prompt\\|my\\|\\)"))))
2218
2219(ert-deftest python-shell-prompt-set-calculated-regexps-4 ()
2220 "Check user defined prompts are set."
2221 (let* ((python-shell-prompt-input-regexps '(""))
2222 (python-shell-prompt-output-regexps '(""))
2223 (python-shell-prompt-regexp "prompt")
2224 (python-shell-prompt-block-regexp "block")
2225 (python-shell-prompt-pdb-regexp "pdb")
2226 (python-shell-prompt-output-regexp "output")
2227 (python-shell--prompt-calculated-input-regexp nil)
2228 (python-shell--prompt-calculated-output-regexp nil)
2229 (python-shell-prompt-detect-enabled nil))
2230 (python-shell-prompt-set-calculated-regexps)
2231 (should (string= python-shell--prompt-calculated-input-regexp
2232 "^\\(prompt\\|block\\|pdb\\|\\)"))
2233 (should (string= python-shell--prompt-calculated-output-regexp
2234 "^\\(output\\|\\)"))))
2235
2236(ert-deftest python-shell-prompt-set-calculated-regexps-5 ()
2237 "Check order of regexps (larger first)."
2238 (let* ((python-shell-prompt-input-regexps '("extralargeinputprompt" "sml"))
2239 (python-shell-prompt-output-regexps '("extralargeoutputprompt" "sml"))
2240 (python-shell-prompt-regexp "in")
2241 (python-shell-prompt-block-regexp "block")
2242 (python-shell-prompt-pdb-regexp "pdf")
2243 (python-shell-prompt-output-regexp "output")
2244 (python-shell--prompt-calculated-input-regexp nil)
2245 (python-shell--prompt-calculated-output-regexp nil)
2246 (python-shell-prompt-detect-enabled nil))
2247 (python-shell-prompt-set-calculated-regexps)
2248 (should (string= python-shell--prompt-calculated-input-regexp
2249 "^\\(extralargeinputprompt\\|block\\|pdf\\|sml\\|in\\)"))
2250 (should (string= python-shell--prompt-calculated-output-regexp
2251 "^\\(extralargeoutputprompt\\|output\\|sml\\)"))))
2252
2253(ert-deftest python-shell-prompt-set-calculated-regexps-6 ()
2254 "Check detected prompts are included `regexp-quote'd."
2255 (skip-unless (executable-find python-tests-shell-interpreter))
2256 (let* ((python-shell-prompt-input-regexps '(""))
2257 (python-shell-prompt-output-regexps '(""))
2258 (python-shell-prompt-regexp "")
2259 (python-shell-prompt-block-regexp "")
2260 (python-shell-prompt-pdb-regexp "")
2261 (python-shell-prompt-output-regexp "")
2262 (python-shell--prompt-calculated-input-regexp nil)
2263 (python-shell--prompt-calculated-output-regexp nil)
2264 (python-shell-prompt-detect-enabled t)
2265 (process-environment process-environment)
2266 (startup-code (concat "import sys\n"
2267 "sys.ps1 = 'p.> '\n"
2268 "sys.ps2 = '..> '\n"
2269 "sys.ps3 = 'o.t '\n"))
2270 (startup-file (python-shell--save-temp-file startup-code)))
2271 (unwind-protect
2272 (progn
2273 (setenv "PYTHONSTARTUP" startup-file)
2274 (python-shell-prompt-set-calculated-regexps)
2275 (should (string= python-shell--prompt-calculated-input-regexp
2276 "^\\(\\.\\.> \\|p\\.> \\|\\)"))
2277 (should (string= python-shell--prompt-calculated-output-regexp
2278 "^\\(o\\.t \\|\\)")))
2279 (ignore-errors (delete-file startup-file)))))
1891 2280
1892 2281
1893;;; Shell completion 2282;;; Shell completion
@@ -3269,6 +3658,11 @@ def foo(a, b, c):
3269 (python-util-forward-comment -1) 3658 (python-util-forward-comment -1)
3270 (should (= (point) (point-min))))) 3659 (should (= (point) (point-min)))))
3271 3660
3661(ert-deftest python-util-valid-regexp-p-1 ()
3662 (should (python-util-valid-regexp-p ""))
3663 (should (python-util-valid-regexp-p python-shell-prompt-regexp))
3664 (should (not (python-util-valid-regexp-p "\\("))))
3665
3272 3666
3273;;; Electricity 3667;;; Electricity
3274 3668