Notepad++ editorhook doesn't work for %edit if you try to edit an object from a file whose path has spaces.
Diagnosis
The %edit magic single-quotes the path if it has spaces, before passing to the editor hook:
|
if " " in quoted: |
|
quoted = "'%s'" % quoted |
|
self.shell.hooks.editor(quoted, lineno) |
Then the default editor hook expects a safe filename, and joins it into a string to use in a Popen call:
|
proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename), |
|
shell=True) |
(Notice that it DOES quote the editor path, conditionally, so that is an inconsistency in how it treats the two paths:
|
# Enclose in quotes if necessary and legal |
|
if ' ' in editor and os.path.isfile(editor) and editor[0] != '"': |
|
editor = '"%s"' % editor |
)
However, the editor hooker makes an editor hook which expects the filename to be an unescaped string, and then uses shlex.quote to substitute it into a template and do the call:
|
cmd = template.format(filename=shlex.quote(filename), line=line) |
Solution
In my opinion, the responsibility of escaping should be moved down to the callee, because taking a quoted filepath is weird.
This will break people's custom hooks which correct for this bug.
- But there is already a test which calls a custom editor hook with unquoted spaces:
|
get_ipython().hooks.editor("the file", 64) |
- And
_edit_macro also calls the editor hook without quoting:
|
filename = self.shell.mktempfile(macro.value) |
|
self.shell.hooks.editor(filename) |
I suspect that breaks if the temp folder is on a path with spaces.
The escaping is also not the best because it doesn't check for existing special characters. It should just use a safer call, if available.
Also, there should be more consistency between how the default and the custom process calls are done.
Also, %edit takes the absolute path, which might lengthen error messages unnecessarily.
|
quoted = filename = str(filepath.absolute()) |
Notepad++ editorhook doesn't work for %edit if you try to edit an object from a file whose path has spaces.
Diagnosis
The
%editmagic single-quotes the path if it has spaces, before passing to the editor hook:ipython/IPython/core/magics/code.py
Lines 723 to 725 in cbac235
Then the default editor hook expects a safe filename, and joins it into a string to use in a Popen call:
ipython/IPython/core/hooks.py
Lines 76 to 77 in cbac235
(Notice that it DOES quote the editor path, conditionally, so that is an inconsistency in how it treats the two paths:
ipython/IPython/core/hooks.py
Lines 71 to 73 in cbac235
However, the editor hooker makes an editor hook which expects the filename to be an unescaped string, and then uses
shlex.quoteto substitute it into a template and do the call:ipython/IPython/lib/editorhooks.py
Line 49 in cbac235
Solution
In my opinion, the responsibility of escaping should be moved down to the callee, because taking a quoted filepath is weird.
This will break people's custom hooks which correct for this bug.
ipython/tests/test_editorhooks.py
Line 25 in cbac235
_edit_macroalso calls the editor hook without quoting:ipython/IPython/core/magics/code.py
Lines 539 to 540 in cbac235
I suspect that breaks if the temp folder is on a path with spaces.
The escaping is also not the best because it doesn't check for existing special characters. It should just use a safer call, if available.
Also, there should be more consistency between how the default and the custom process calls are done.
Also, %edit takes the absolute path, which might lengthen error messages unnecessarily.
ipython/IPython/core/magics/code.py
Line 722 in cbac235