Make python.el work with IPython automatically.

* lisp/progmodes/python.el:
(python-shell-completion-setup-code): New value supporting iPython.
(python-shell-completion-string-code): New value supporting iPython.
(python-shell-completion-get-completions): Use them.
(python-shell-completion-module-string-code): Make obsolete.
(python-shell-prompt-input-regexps)
(python-shell-prompt-output-regexps): Add safeguard for ipdb.
(python-shell-output-filter): Fix comment typo.

* test/automated/python-tests.el:
(python-util-clone-local-variables-1): Fix test.

Fixes: debbugs:15510
parent 880b7166
...@@ -670,6 +670,23 @@ display a "Homepage" header.) ...@@ -670,6 +670,23 @@ display a "Homepage" header.)
** In Prolog mode, `prolog-use-smie' has been removed, ** In Prolog mode, `prolog-use-smie' has been removed,
along with the non-SMIE indentation code. along with the non-SMIE indentation code.
** Python mode
*** Out of the box support for CPython, iPython and readline based shells.
**** `python-shell-completion-module-string-code` is no longer used.
*** Automatic shell prompt detection.
**** New user options:
***** `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`.
*** Python shell support for remote hosts via tramp.
*** Correct display of line numbers for code sent to the Python shell.
** Remember ** Remember
*** The new command `remember-notes' creates a buffer that is saved on exit. *** The new command `remember-notes' creates a buffer that is saved on exit.
......
2014-07-20 Fabián Ezequiel Gallina <fgallina@gnu.org>
Make python.el work with IPython automatically. (Bug#15510)
* progmodes/python.el:
(python-shell-completion-setup-code): New value supporting iPython.
(python-shell-completion-string-code): New value supporting iPython.
(python-shell-completion-get-completions): Use them.
(python-shell-completion-module-string-code): Make obsolete.
(python-shell-prompt-input-regexps)
(python-shell-prompt-output-regexps): Add safeguard for ipdb.
(python-shell-output-filter): Fix comment typo.
2014-07-19 Fabián Ezequiel Gallina <fgallina@gnu.org> 2014-07-19 Fabián Ezequiel Gallina <fgallina@gnu.org>
Fix Python shell prompts detection for remote hosts. Fix Python shell prompts detection for remote hosts.
......
...@@ -62,16 +62,46 @@ ...@@ -62,16 +62,46 @@
;; (add-hook 'python-mode-hook ;; (add-hook 'python-mode-hook
;; (lambda () (setq forward-sexp-function nil))) ;; (lambda () (setq forward-sexp-function nil)))
;; Shell interaction: is provided and allows you to easily execute any ;; Shell interaction: is provided and allows opening Python shells
;; block of code of your current buffer in an inferior Python process. ;; inside Emacs and executing any block of code of your current buffer
;; This relies upon having prompts for input (e.g. ">>> " and "... " ;; in that inferior Python process.
;; in standard Python shell) and output (e.g. "Out[1]: " in iPython)
;; detected properly. Failing that Emacs may hang but, in the case ;; Besides that only the standard CPython (2.x and 3.x) shell and
;; that happens, you can recover with \\[keyboard-quit]. To avoid ;; IPython are officially supported out of the box, the interaction
;; this issue, a two-step prompt autodetection mechanism is provided: ;; should support any other readline based Python shells as well
;; the first step is manual and consists of a collection of regular ;; (e.g. Jython and Pypy have been reported to work). You can change
;; expressions matching common prompts for Python shells stored in ;; your default interpreter and commandline arguments by setting the
;; `python-shell-prompt-input-regexps' and ;; `python-shell-interpreter' and `python-shell-interpreter-args'
;; variables. This example enables IPython globally:
;; (setq python-shell-interpreter "ipython"
;; python-shell-interpreter-args "-i")
;; Using the "console" subcommand to start IPython in server-client
;; mode is known to fail intermittently due a bug on IPython itself
;; (see URL `http://debbugs.gnu.org/cgi/bugreport.cgi?bug=18052#27').
;; There seems to be a race condition in the IPython server (A.K.A
;; kernel) when code is sent while it is still initializing, sometimes
;; causing the shell to get stalled. With that said, if an IPython
;; kernel is already running, "console --existing" seems to work fine.
;; Running IPython on Windows needs more tweaking. The way you should
;; set `python-shell-interpreter' and `python-shell-interpreter-args'
;; is as follows (of course you need to modify the paths according to
;; your system):
;; (setq python-shell-interpreter "C:\\Python27\\python.exe"
;; python-shell-interpreter-args
;; "-i C:\\Python27\\Scripts\\ipython-script.py")
;; The interaction relies upon having prompts for input (e.g. ">>> "
;; and "... " in standard Python shell) and output (e.g. "Out[1]: " in
;; IPython) detected properly. Failing that Emacs may hang but, in
;; the case that happens, you can recover with \\[keyboard-quit]. To
;; avoid this issue, a two-step prompt autodetection mechanism is
;; provided: the first step is manual and consists of a collection of
;; regular expressions matching common prompts for Python shells
;; stored in `python-shell-prompt-input-regexps' and
;; `python-shell-prompt-output-regexps', and dir-local friendly vars ;; `python-shell-prompt-output-regexps', and dir-local friendly vars
;; `python-shell-prompt-regexp', `python-shell-prompt-block-regexp', ;; `python-shell-prompt-regexp', `python-shell-prompt-block-regexp',
;; `python-shell-prompt-output-regexp' which are appended to the ;; `python-shell-prompt-output-regexp' which are appended to the
...@@ -81,51 +111,23 @@ ...@@ -81,51 +111,23 @@
;; modify its behavior. ;; modify its behavior.
;; Shell completion: hitting tab will try to complete the current ;; Shell completion: hitting tab will try to complete the current
;; word. Shell completion is implemented in a way that if you change ;; word. Shell completion is implemented in such way that if you
;; the `python-shell-interpreter' to any other (for example IPython) ;; change the `python-shell-interpreter' it should be possible to
;; it should be easy to integrate another way to calculate ;; integrate custom logic to calculate completions. To achieve this
;; completions. You just need to specify your custom ;; you just need to set `python-shell-completion-setup-code' and
;; `python-shell-completion-setup-code' and ;; `python-shell-completion-string-code'. The default provided code,
;; `python-shell-completion-string-code'. ;; enables autocompletion for both CPython and IPython (and ideally
;; any readline based Python shell). This code depends on the
;; Here is a complete example of the settings you would use for ;; readline module, so if you are using some Operating System that
;; iPython 0.11: ;; bundles Python without it (like Windows), installing pyreadline
;; from URL `http://ipython.scipy.org/moin/PyReadline/Intro' should
;; (setq ;; suffice. To troubleshoot why you are not getting any completions
;; python-shell-interpreter "ipython" ;; you can try the following in your Python shell:
;; python-shell-interpreter-args ""
;; python-shell-completion-setup-code
;; "from IPython.core.completerlib import module_completion"
;; python-shell-completion-module-string-code
;; "';'.join(module_completion('''%s'''))\n"
;; python-shell-completion-string-code
;; "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
;; For iPython 0.10 everything would be the same except for
;; `python-shell-completion-string-code' and
;; `python-shell-completion-module-string-code':
;; (setq python-shell-completion-string-code
;; "';'.join(__IP.complete('''%s'''))\n"
;; python-shell-completion-module-string-code "")
;; Unfortunately running iPython on Windows needs some more tweaking.
;; The way you must set `python-shell-interpreter' and
;; `python-shell-interpreter-args' is as follows:
;; (setq
;; python-shell-interpreter "C:\\Python27\\python.exe"
;; python-shell-interpreter-args
;; "-i C:\\Python27\\Scripts\\ipython-script.py")
;; That will spawn the iPython process correctly (Of course you need ;; >>> import readline, rlcompleter
;; to modify the paths according to your system).
;; Please note that the default completion system depends on the ;; If you see an error, then you need to either install pyreadline or
;; readline module, so if you are using some Operating System that ;; setup custom code that avoids that dependency.
;; bundles Python without it (like Windows) just install the
;; pyreadline from http://ipython.scipy.org/moin/PyReadline/Intro and
;; you should be good to go.
;; Shell virtualenv support: The shell also contains support for ;; Shell virtualenv support: The shell also contains support for
;; virtualenvs and other special environment modifications thanks to ;; virtualenvs and other special environment modifications thanks to
...@@ -1740,14 +1742,18 @@ position, else returns nil." ...@@ -1740,14 +1742,18 @@ position, else returns nil."
(defcustom python-shell-prompt-input-regexps (defcustom python-shell-prompt-input-regexps
'(">>> " "\\.\\.\\. " ; Python '(">>> " "\\.\\.\\. " ; Python
"In \\[[0-9]+\\]: ") ; iPython "In \\[[0-9]+\\]: " ; IPython
;; Using ipdb outside IPython may fail to cleanup and leave static
;; IPython prompts activated, this adds some safeguard for that.
"In : " "\\.\\.\\.: ")
"List of regular expressions matching input prompts." "List of regular expressions matching input prompts."
:type '(repeat string) :type '(repeat string)
:version "24.4") :version "24.4")
(defcustom python-shell-prompt-output-regexps (defcustom python-shell-prompt-output-regexps
'("" ; Python '("" ; Python
"Out\\[[0-9]+\\]: ") ; iPython "Out\\[[0-9]+\\]: " ; IPython
"Out :") ; ipdb safeguard
"List of regular expressions matching output prompts." "List of regular expressions matching output prompts."
:type '(repeat string) :type '(repeat string)
:version "24.4") :version "24.4")
...@@ -2398,7 +2404,7 @@ detecting a prompt at the end of the buffer." ...@@ -2398,7 +2404,7 @@ detecting a prompt at the end of the buffer."
(when (string-match (when (string-match
python-shell--prompt-calculated-output-regexp python-shell--prompt-calculated-output-regexp
python-shell-output-filter-buffer) python-shell-output-filter-buffer)
;; Some shells, like iPython might append a prompt before the ;; Some shells, like IPython might append a prompt before the
;; output, clean that. ;; output, clean that.
(setq python-shell-output-filter-buffer (setq python-shell-output-filter-buffer
(substring python-shell-output-filter-buffer (match-end 0))))) (substring python-shell-output-filter-buffer (match-end 0)))))
...@@ -2608,23 +2614,35 @@ This function takes the list of setup code to send from the ...@@ -2608,23 +2614,35 @@ This function takes the list of setup code to send from the
(defcustom python-shell-completion-setup-code (defcustom python-shell-completion-setup-code
"try: "try:
import readline import readline, rlcompleter
except ImportError: except ImportError:
def __COMPLETER_all_completions(text): [] def __PYTHON_EL_get_completions(text):
return []
else: else:
import rlcompleter def __PYTHON_EL_get_completions(text):
readline.set_completer(rlcompleter.Completer().complete)
def __COMPLETER_all_completions(text):
import sys
completions = [] completions = []
try: try:
splits = text.split()
is_module = splits and splits[0] in ('from', 'import')
is_ipython = getattr(
__builtins__, '__IPYTHON__',
getattr(__builtins__, '__IPYTHON__active', False))
if is_module:
from IPython.core.completerlib import module_completion
completions = module_completion(text.strip())
elif is_ipython and getattr(__builtins__, '__IP', None):
completions = __IP.complete(text)
elif is_ipython and getattr(__builtins__, 'get_ipython', None):
completions = get_ipython().Completer.all_completions(text)
else:
i = 0 i = 0
while True: while True:
res = readline.get_completer()(text, i) res = readline.get_completer()(text, i)
if not res: break if not res:
break
i += 1 i += 1
completions.append(res) completions.append(res)
except NameError: except:
pass pass
return completions" return completions"
"Code used to setup completion in inferior Python processes." "Code used to setup completion in inferior Python processes."
...@@ -2632,24 +2650,18 @@ else: ...@@ -2632,24 +2650,18 @@ else:
:group 'python) :group 'python)
(defcustom python-shell-completion-string-code (defcustom python-shell-completion-string-code
"';'.join(__COMPLETER_all_completions('''%s'''))\n" "';'.join(__PYTHON_EL_get_completions('''%s'''))\n"
"Python code used to get a string of completions separated by semicolons." "Python code used to get a string of completions separated by semicolons.
The string passed to the function is the current python name or
the full statement in the case of imports."
:type 'string :type 'string
:group 'python) :group 'python)
(defcustom python-shell-completion-module-string-code "" (define-obsolete-variable-alias
"Python code used to get completions separated by semicolons for imports. 'python-shell-completion-module-string-code
'python-shell-completion-string-code
For IPython v0.11, add the following line to "24.4"
`python-shell-completion-setup-code': "Completion string code must also autocomplete modules.")
from IPython.core.completerlib import module_completion
and use the following as the value of this variable:
';'.join(module_completion('''%s'''))\n"
:type 'string
:group 'python)
(defcustom python-shell-completion-pdb-string-code (defcustom python-shell-completion-pdb-string-code
"';'.join(globals().keys() + locals().keys())" "';'.join(globals().keys() + locals().keys())"
...@@ -2672,33 +2684,23 @@ LINE is used to detect the context on how to complete given INPUT." ...@@ -2672,33 +2684,23 @@ LINE is used to detect the context on how to complete given INPUT."
(re-search-backward "^") (re-search-backward "^")
(python-util-forward-comment) (python-util-forward-comment)
(point)))))) (point))))))
(completion-context (completion-code
;; Check whether a prompt matches a pdb string, an import ;; Check whether a prompt matches a pdb string, an import
;; statement or just the standard prompt and use the ;; statement or just the standard prompt and use the
;; correct python-shell-completion-*-code string ;; correct python-shell-completion-*-code string
(cond ((and (> (length python-shell-completion-pdb-string-code) 0) (cond ((and (> (length python-shell-completion-pdb-string-code) 0)
(string-match (string-match
(concat "^" python-shell-prompt-pdb-regexp) prompt)) (concat "^" python-shell-prompt-pdb-regexp) prompt))
'pdb) python-shell-completion-pdb-string-code)
((and (>
(length python-shell-completion-module-string-code) 0)
(string-match
python-shell--prompt-calculated-input-regexp prompt)
(string-match "^[ \t]*\\(from\\|import\\)[ \t]" line))
'import)
((string-match ((string-match
python-shell--prompt-calculated-input-regexp prompt) python-shell--prompt-calculated-input-regexp prompt)
'default) python-shell-completion-string-code)
(t nil))) (t nil)))
(completion-code
(pcase completion-context
(`pdb python-shell-completion-pdb-string-code)
(`import python-shell-completion-module-string-code)
(`default python-shell-completion-string-code)
(_ nil)))
(input (input
(if (eq completion-context 'import) (if (string-match
(replace-regexp-in-string "^[ \t]+" "" line) (python-rx (+ space) (or "from" "import") space)
line)
line
input))) input)))
(and completion-code (and completion-code
(> (length input) 0) (> (length input) 0)
......
2014-07-20 Fabián Ezequiel Gallina <fgallina@gnu.org>
* automated/python-tests.el:
(python-util-clone-local-variables-1): Fix test.
2014-07-17 Fabián Ezequiel Gallina <fgallina@gnu.org> 2014-07-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
* automated/python-tests.el (python-shell-make-comint-1): * automated/python-tests.el (python-shell-make-comint-1):
......
...@@ -3619,8 +3619,6 @@ def foo(a, b, c): ...@@ -3619,8 +3619,6 @@ def foo(a, b, c):
(python-shell-extra-pythonpaths "/home/user/pylib/") (python-shell-extra-pythonpaths "/home/user/pylib/")
(python-shell-completion-setup-code (python-shell-completion-setup-code
. "from IPython.core.completerlib import module_completion") . "from IPython.core.completerlib import module_completion")
(python-shell-completion-module-string-code
. "';'.join(module_completion('''%s'''))\n")
(python-shell-completion-string-code (python-shell-completion-string-code
. "';'.join(get_ipython().Completer.all_completions('''%s'''))\n") . "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
(python-shell-virtualenv-path (python-shell-virtualenv-path
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment