Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Use repr() to make quoted strings #1019

Merged
merged 3 commits into from

3 participants

Thomas Kluyver Robert Kern Fernando Perez
Thomas Kluyver
Owner

Should at least begin to fix #1009, by correctly escaping strings with \U or \u in them.

This only broke a few tests because repr defaults to 'single quotes', whereas our implementation defaulted to "double quotes". I've fixed those.

Bonus fix: a couple of config tests were failing on Python 3.

Robert Kern
Collaborator

Note that %r will do the repr() for you.

('%r' % value) == ('%s' % repr(value))
Thomas Kluyver
Owner

Good point. Done.

Fernando Perez fperez merged commit 268ecbe into from
Fernando Perez
Owner

Thanks, looks great (and to @rkern for the review!). Merged.

Fernando Perez fperez referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
7 IPython/config/tests/test_configurable.py
View
@@ -31,7 +31,7 @@
)
from IPython.config.loader import Config
-
+from IPython.utils.py3compat import PY3
#-----------------------------------------------------------------------------
# Test cases
@@ -62,6 +62,11 @@ class MyConfigurable(Configurable):
Current: 4.0
The integer b."""
+# On Python 3, the Integer trait is a synonym for Int
+if PY3:
+ mc_help = mc_help.replace(u"<Integer>", u"<Int>")
+ mc_help_inst = mc_help_inst.replace(u"<Integer>", u"<Int>")
+
class Foo(Configurable):
a = Integer(0, config=True, help="The integer a.")
b = Unicode('nope', config=True)
26 IPython/core/inputsplitter.py
View
@@ -75,7 +75,6 @@
# IPython modules
from IPython.core.splitinput import split_user_input, LineInfo
-from IPython.utils.text import make_quoted_expr
from IPython.utils.py3compat import cast_unicode
#-----------------------------------------------------------------------------
@@ -503,8 +502,7 @@ def transform_assign_system(line):
if m is not None:
cmd = m.group('cmd')
lhs = m.group('lhs')
- expr = make_quoted_expr(cmd)
- new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
+ new_line = '%s = get_ipython().getoutput(%r)' % (lhs, cmd)
return new_line
return line
@@ -518,8 +516,7 @@ def transform_assign_magic(line):
if m is not None:
cmd = m.group('cmd')
lhs = m.group('lhs')
- expr = make_quoted_expr(cmd)
- new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
+ new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
return new_line
return line
@@ -560,13 +557,13 @@ def _make_help_call(target, esc, lspace, next_input=None):
method = 'pinfo2' if esc == '??' \
else 'psearch' if '*' in target \
else 'pinfo'
- arg = make_quoted_expr(" ".join([method, target]))
+ arg = " ".join([method, target])
if next_input:
- tpl = '%sget_ipython().magic(%s, next_input=%s)'
- return tpl % (lspace, arg, make_quoted_expr(next_input))
+ tpl = '%sget_ipython().magic(%r, next_input=%r)'
+ return tpl % (lspace, arg, next_input)
else:
- return '%sget_ipython().magic(%s)' % (lspace, arg)
+ return '%sget_ipython().magic(%r)' % (lspace, arg)
_initial_space_re = re.compile(r'\s*')
_help_end_re = re.compile(r"""(%?
@@ -610,15 +607,13 @@ def __init__(self):
def _tr_system(line_info):
"Translate lines escaped with: !"
cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
- return '%sget_ipython().system(%s)' % (line_info.pre,
- make_quoted_expr(cmd))
+ return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
@staticmethod
def _tr_system2(line_info):
"Translate lines escaped with: !!"
cmd = line_info.line.lstrip()[2:]
- return '%sget_ipython().getoutput(%s)' % (line_info.pre,
- make_quoted_expr(cmd))
+ return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
@staticmethod
def _tr_help(line_info):
@@ -632,9 +627,8 @@ def _tr_help(line_info):
@staticmethod
def _tr_magic(line_info):
"Translate lines escaped with: %"
- tpl = '%sget_ipython().magic(%s)'
- cmd = make_quoted_expr(' '.join([line_info.ifun,
- line_info.the_rest]).strip())
+ tpl = '%sget_ipython().magic(%r)'
+ cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
return tpl % (line_info.pre, cmd)
@staticmethod
18 IPython/core/prefilter.py
View
@@ -36,7 +36,6 @@
from IPython.core import page
from IPython.utils.traitlets import List, Integer, Any, Unicode, CBool, Bool, Instance
-from IPython.utils.text import make_quoted_expr
from IPython.utils.autoattr import auto_attr
#-----------------------------------------------------------------------------
@@ -405,8 +404,8 @@ def transform(self, line, continue_prompt):
if m is not None:
cmd = m.group('cmd')
lhs = m.group('lhs')
- expr = make_quoted_expr("sc =%s" % cmd)
- new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
+ expr = "sc =%s" % cmd
+ new_line = '%s = get_ipython().magic(%r)' % (lhs, expr)
return new_line
return line
@@ -424,8 +423,7 @@ def transform(self, line, continue_prompt):
if m is not None:
cmd = m.group('cmd')
lhs = m.group('lhs')
- expr = make_quoted_expr(cmd)
- new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
+ new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
return new_line
return line
@@ -733,8 +731,7 @@ def handle(self, line_info):
transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
# pre is needed, because it carries the leading whitespace. Otherwise
# aliases won't work in indented sections.
- line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
- make_quoted_expr(transformed))
+ line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
return line_out
@@ -762,8 +759,7 @@ def handle(self, line_info):
return magic_handler.handle(line_info)
else:
cmd = line.lstrip().lstrip(ESC_SHELL)
- line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
- make_quoted_expr(cmd))
+ line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, cmd)
return line_out
@@ -786,8 +782,8 @@ def handle(self, line_info):
"""Execute magic functions."""
ifun = line_info.ifun
the_rest = line_info.the_rest
- cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
- make_quoted_expr(ifun + " " + the_rest))
+ cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
+ (ifun + " " + the_rest))
return cmd
30 IPython/core/tests/test_handlers.py
View
@@ -61,10 +61,10 @@ def test_handlers():
ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
ip.alias_manager.alias_table['d'] = (0, 'true')
run([(i,py3compat.u_format(o)) for i,o in \
- [("an_alias", 'get_ipython().system({u}"true ")'), # alias
+ [("an_alias", "get_ipython().system({u}'true ')"), # alias
# Below: recursive aliases should expand whitespace-surrounded
# chars, *not* initial chars which happen to be aliases:
- ("top", 'get_ipython().system({u}"d:/cygwin/top ")'),
+ ("top", "get_ipython().system({u}'d:/cygwin/top ')"),
]])
ip.system = old_system_cmd
@@ -76,15 +76,15 @@ def test_handlers():
# line.
run([(i,py3compat.u_format(o)) for i,o in \
[('"no change"', '"no change"'), # normal
- ("!true", 'get_ipython().system({u}"true")'), # shell_escapes
- ("!! true", 'get_ipython().magic({u}"sx true")'), # shell_escapes + magic
- ("!!true", 'get_ipython().magic({u}"sx true")'), # shell_escapes + magic
- ("%lsmagic", 'get_ipython().magic({u}"lsmagic ")'), # magic
- ("lsmagic", 'get_ipython().magic({u}"lsmagic ")'), # magic
+ (u"!true", "get_ipython().system({u}'true')"), # shell_escapes
+ (u"!! true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
+ (u"!!true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
+ (u"%lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
+ (u"lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
#("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
# post-esc-char whitespace goes inside
- ("! true", 'get_ipython().system({u}" true")'),
+ (u"! true", "get_ipython().system({u}' true')"),
# handle_help
@@ -99,19 +99,19 @@ def test_handlers():
ip.prefilter_manager.multi_line_specials = False
# W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
run([
- ('if 1:\n !true', 'if 1:\n !true'),
- ('if 1:\n lsmagic', 'if 1:\n lsmagic'),
- ('if 1:\n an_alias', 'if 1:\n an_alias'),
+ (u'if 1:\n !true', u'if 1:\n !true'),
+ (u'if 1:\n lsmagic', u'if 1:\n lsmagic'),
+ (u'if 1:\n an_alias', u'if 1:\n an_alias'),
])
ip.prefilter_manager.multi_line_specials = True
# initial indents must be preserved.
run([(i,py3compat.u_format(o)) for i,o in \
- [('if 1:\n !true', 'if 1:\n get_ipython().system({u}"true")'),
- ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic({u}"lsmagic ")'),
- ('if 1:\n an_alias', 'if 1:\n get_ipython().system({u}"true ")'),
+ [(u'if 1:\n !true', "if 1:\n get_ipython().system({u}'true')"),
+ (u'if 2:\n lsmagic', "if 2:\n get_ipython().magic({u}'lsmagic ')"),
+ (u'if 1:\n an_alias', "if 1:\n get_ipython().system({u}'true ')"),
# Weird one
- ('if 1:\n !!true', 'if 1:\n get_ipython().magic({u}"sx true")'),
+ (u'if 1:\n !!true', "if 1:\n get_ipython().magic({u}'sx true')"),
# Even with m_l_s on, autocall is off even with special chars
('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
62 IPython/core/tests/test_inputsplitter.py
View
@@ -405,16 +405,16 @@ def transform_checker(tests, func):
syntax = \
dict(assign_system =
[(i,py3compat.u_format(o)) for i,o in \
- [('a =! ls', 'a = get_ipython().getoutput({u}"ls")'),
- ('b = !ls', 'b = get_ipython().getoutput({u}"ls")'),
+ [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
+ (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact
]],
assign_magic =
[(i,py3compat.u_format(o)) for i,o in \
- [('a =% who', 'a = get_ipython().magic({u}"who")'),
- ('b = %who', 'b = get_ipython().magic({u}"who")'),
+ [(u'a =% who', "a = get_ipython().magic({u}'who')"),
+ (u'b = %who', "b = get_ipython().magic({u}'who')"),
('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact
]],
@@ -442,43 +442,45 @@ def transform_checker(tests, func):
# System calls
escaped_shell =
[(i,py3compat.u_format(o)) for i,o in \
- [ ('!ls', 'get_ipython().system({u}"ls")'),
+ [ (u'!ls', "get_ipython().system({u}'ls')"),
# Double-escape shell, this means to capture the output of the
# subprocess and return it
- ('!!ls', 'get_ipython().getoutput({u}"ls")'),
+ (u'!!ls', "get_ipython().getoutput({u}'ls')"),
]],
# Help/object info
escaped_help =
[(i,py3compat.u_format(o)) for i,o in \
- [ ('?', 'get_ipython().show_usage()'),
- ('?x1', 'get_ipython().magic({u}"pinfo x1")'),
- ('??x2', 'get_ipython().magic({u}"pinfo2 x2")'),
- ('?a.*s', 'get_ipython().magic({u}"psearch a.*s")'),
- ('?%hist', 'get_ipython().magic({u}"pinfo %hist")'),
- ('?abc = qwe', 'get_ipython().magic({u}"pinfo abc")'),
+ [ (u'?', 'get_ipython().show_usage()'),
+ (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
+ (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
+ (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
+ (u'?%hist', "get_ipython().magic({u}'pinfo %hist')"),
+ (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
]],
end_help =
[(i,py3compat.u_format(o)) for i,o in \
- [ ('x3?', 'get_ipython().magic({u}"pinfo x3")'),
- ('x4??', 'get_ipython().magic({u}"pinfo2 x4")'),
- ('%hist?', 'get_ipython().magic({u}"pinfo %hist")'),
- ('f*?', 'get_ipython().magic({u}"psearch f*")'),
- ('ax.*aspe*?', 'get_ipython().magic({u}"psearch ax.*aspe*")'),
- ('a = abc?', 'get_ipython().magic({u}"pinfo abc", next_input={u}"a = abc")'),
- ('a = abc.qe??', 'get_ipython().magic({u}"pinfo2 abc.qe", next_input={u}"a = abc.qe")'),
- ('a = *.items?', 'get_ipython().magic({u}"psearch *.items", next_input={u}"a = *.items")'),
- ('plot(a?', 'get_ipython().magic({u}"pinfo a", next_input={u}"plot(a")'),
- ('a*2 #comment?', 'a*2 #comment?'),
+ [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
+ (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
+ (u'%hist?', "get_ipython().magic({u}'pinfo %hist')"),
+ (u'f*?', "get_ipython().magic({u}'psearch f*')"),
+ (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
+ (u'a = abc?', "get_ipython().magic({u}'pinfo abc', next_input={u}'a = abc')"),
+ (u'a = abc.qe??', "get_ipython().magic({u}'pinfo2 abc.qe', next_input={u}'a = abc.qe')"),
+ (u'a = *.items?', "get_ipython().magic({u}'psearch *.items', next_input={u}'a = *.items')"),
+ (u'plot(a?', "get_ipython().magic({u}'pinfo a', next_input={u}'plot(a')"),
+ (u'a*2 #comment?', 'a*2 #comment?'),
]],
# Explicit magic calls
escaped_magic =
[(i,py3compat.u_format(o)) for i,o in \
- [ ('%cd', 'get_ipython().magic({u}"cd")'),
- ('%cd /home', 'get_ipython().magic({u}"cd /home")'),
- (' %magic', ' get_ipython().magic({u}"magic")'),
+ [ (u'%cd', "get_ipython().magic({u}'cd')"),
+ (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
+ # Backslashes need to be escaped.
+ (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
+ (u' %magic', " get_ipython().magic({u}'magic')"),
]],
# Quoting with separate arguments
@@ -508,11 +510,11 @@ def transform_checker(tests, func):
# Check that we transform prompts before other transforms
mixed =
[(i,py3compat.u_format(o)) for i,o in \
- [ ('In [1]: %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
- ('>>> %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
- ('In [2]: !ls', 'get_ipython().system({u}"ls")'),
- ('In [3]: abs?', 'get_ipython().magic({u}"pinfo abs")'),
- ('In [4]: b = %who', 'b = get_ipython().magic({u}"who")'),
+ [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
+ (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
+ (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
+ (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
+ (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
]],
)
34 IPython/utils/text.py
View
@@ -295,40 +295,6 @@ def esc_quotes(strng):
return strng.replace('"','\\"').replace("'","\\'")
-def make_quoted_expr(s):
- """Return string s in appropriate quotes, using raw string if possible.
-
- XXX - example removed because it caused encoding errors in documentation
- generation. We need a new example that doesn't contain invalid chars.
-
- Note the use of raw string and padding at the end to allow trailing
- backslash.
- """
-
- tail = ''
- tailpadding = ''
- raw = ''
- ucode = '' if py3compat.PY3 else 'u'
- if "\\" in s:
- raw = 'r'
- if s.endswith('\\'):
- tail = '[:-1]'
- tailpadding = '_'
- if '"' not in s:
- quote = '"'
- elif "'" not in s:
- quote = "'"
- elif '"""' not in s and not s.endswith('"'):
- quote = '"""'
- elif "'''" not in s and not s.endswith("'"):
- quote = "'''"
- else:
- # give up, backslash-escaped string will do
- return '"%s"' % esc_quotes(s)
- res = ucode + raw + quote + s + tailpadding + quote + tail
- return res
-
-
def qw(words,flat=0,sep=None,maxsplit=-1):
"""Similar to Perl's qw() operator, but with some more options.
Something went wrong with that request. Please try again.