Skip to content
This repository

Use repr() to make quoted strings #1019

Merged
merged 3 commits into from over 2 years ago

3 participants

Thomas Kluyver Robert Kern Fernando Perez
Thomas Kluyver
Collaborator

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
Collaborator

Good point. Done.

Fernando Perez fperez merged commit 268ecbe into from November 20, 2011
Fernando Perez fperez closed this November 20, 2011
Fernando Perez
Owner

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

Fernando Perez fperez referenced this pull request from a commit January 10, 2012
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
@@ -31,7 +31,7 @@
31 31
 )
32 32
 
33 33
 from IPython.config.loader import Config
34  
-
  34
+from IPython.utils.py3compat import PY3
35 35
 
36 36
 #-----------------------------------------------------------------------------
37 37
 # Test cases
@@ -62,6 +62,11 @@ class MyConfigurable(Configurable):
62 62
     Current: 4.0
63 63
     The integer b."""
64 64
 
  65
+# On Python 3, the Integer trait is a synonym for Int
  66
+if PY3:
  67
+    mc_help = mc_help.replace(u"<Integer>", u"<Int>")
  68
+    mc_help_inst = mc_help_inst.replace(u"<Integer>", u"<Int>")
  69
+
65 70
 class Foo(Configurable):
66 71
     a = Integer(0, config=True, help="The integer a.")
67 72
     b = Unicode('nope', config=True)
26  IPython/core/inputsplitter.py
@@ -75,7 +75,6 @@
75 75
 
76 76
 # IPython modules
77 77
 from IPython.core.splitinput import split_user_input, LineInfo
78  
-from IPython.utils.text import make_quoted_expr
79 78
 from IPython.utils.py3compat import cast_unicode
80 79
 
81 80
 #-----------------------------------------------------------------------------
@@ -503,8 +502,7 @@ def transform_assign_system(line):
503 502
     if m is not None:
504 503
         cmd = m.group('cmd')
505 504
         lhs = m.group('lhs')
506  
-        expr = make_quoted_expr(cmd)
507  
-        new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
  505
+        new_line = '%s = get_ipython().getoutput(%r)' % (lhs, cmd)
508 506
         return new_line
509 507
     return line
510 508
 
@@ -518,8 +516,7 @@ def transform_assign_magic(line):
518 516
     if m is not None:
519 517
         cmd = m.group('cmd')
520 518
         lhs = m.group('lhs')
521  
-        expr = make_quoted_expr(cmd)
522  
-        new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
  519
+        new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
523 520
         return new_line
524 521
     return line
525 522
 
@@ -560,13 +557,13 @@ def _make_help_call(target, esc, lspace, next_input=None):
560 557
     method  = 'pinfo2' if esc == '??' \
561 558
                 else 'psearch' if '*' in target \
562 559
                 else 'pinfo'
563  
-    arg = make_quoted_expr(" ".join([method, target]))
  560
+    arg = " ".join([method, target])
564 561
     
565 562
     if next_input:
566  
-        tpl = '%sget_ipython().magic(%s, next_input=%s)'
567  
-        return tpl % (lspace, arg, make_quoted_expr(next_input))
  563
+        tpl = '%sget_ipython().magic(%r, next_input=%r)'
  564
+        return tpl % (lspace, arg, next_input)
568 565
     else:
569  
-        return '%sget_ipython().magic(%s)' % (lspace, arg)
  566
+        return '%sget_ipython().magic(%r)' % (lspace, arg)
570 567
 
571 568
 _initial_space_re = re.compile(r'\s*')
572 569
 _help_end_re = re.compile(r"""(%?
@@ -610,15 +607,13 @@ def __init__(self):
610 607
     def _tr_system(line_info):
611 608
         "Translate lines escaped with: !"
612 609
         cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
613  
-        return '%sget_ipython().system(%s)' % (line_info.pre,
614  
-                                               make_quoted_expr(cmd))
  610
+        return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
615 611
 
616 612
     @staticmethod
617 613
     def _tr_system2(line_info):
618 614
         "Translate lines escaped with: !!"
619 615
         cmd = line_info.line.lstrip()[2:]
620  
-        return '%sget_ipython().getoutput(%s)' % (line_info.pre,
621  
-                                                  make_quoted_expr(cmd))
  616
+        return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
622 617
 
623 618
     @staticmethod
624 619
     def _tr_help(line_info):
@@ -632,9 +627,8 @@ def _tr_help(line_info):
632 627
     @staticmethod
633 628
     def _tr_magic(line_info):
634 629
         "Translate lines escaped with: %"
635  
-        tpl = '%sget_ipython().magic(%s)'
636  
-        cmd = make_quoted_expr(' '.join([line_info.ifun,
637  
-                                        line_info.the_rest]).strip())
  630
+        tpl = '%sget_ipython().magic(%r)'
  631
+        cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
638 632
         return tpl % (line_info.pre, cmd)
639 633
 
640 634
     @staticmethod
18  IPython/core/prefilter.py
@@ -36,7 +36,6 @@
36 36
 from IPython.core import page
37 37
 
38 38
 from IPython.utils.traitlets import List, Integer, Any, Unicode, CBool, Bool, Instance
39  
-from IPython.utils.text import make_quoted_expr
40 39
 from IPython.utils.autoattr import auto_attr
41 40
 
42 41
 #-----------------------------------------------------------------------------
@@ -405,8 +404,8 @@ def transform(self, line, continue_prompt):
405 404
         if m is not None:
406 405
             cmd = m.group('cmd')
407 406
             lhs = m.group('lhs')
408  
-            expr = make_quoted_expr("sc =%s" % cmd)
409  
-            new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
  407
+            expr = "sc =%s" % cmd
  408
+            new_line = '%s = get_ipython().magic(%r)' % (lhs, expr)
410 409
             return new_line
411 410
         return line
412 411
 
@@ -424,8 +423,7 @@ def transform(self, line, continue_prompt):
424 423
         if m is not None:
425 424
             cmd = m.group('cmd')
426 425
             lhs = m.group('lhs')
427  
-            expr = make_quoted_expr(cmd)
428  
-            new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
  426
+            new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
429 427
             return new_line
430 428
         return line
431 429
 
@@ -733,8 +731,7 @@ def handle(self, line_info):
733 731
         transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
734 732
         # pre is needed, because it carries the leading whitespace.  Otherwise
735 733
         # aliases won't work in indented sections.
736  
-        line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
737  
-                                         make_quoted_expr(transformed))
  734
+        line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
738 735
 
739 736
         return line_out
740 737
 
@@ -762,8 +759,7 @@ def handle(self, line_info):
762 759
             return magic_handler.handle(line_info)
763 760
         else:
764 761
             cmd = line.lstrip().lstrip(ESC_SHELL)
765  
-            line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
766  
-                                             make_quoted_expr(cmd))
  762
+            line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, cmd)
767 763
         return line_out
768 764
 
769 765
 
@@ -786,8 +782,8 @@ def handle(self, line_info):
786 782
         """Execute magic functions."""
787 783
         ifun    = line_info.ifun
788 784
         the_rest = line_info.the_rest
789  
-        cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
790  
-                                   make_quoted_expr(ifun + " " + the_rest))
  785
+        cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
  786
+                                                    (ifun + " " + the_rest))
791 787
         return cmd
792 788
 
793 789
 
30  IPython/core/tests/test_handlers.py
@@ -61,10 +61,10 @@ def test_handlers():
61 61
     ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
62 62
     ip.alias_manager.alias_table['d'] =   (0, 'true')
63 63
     run([(i,py3compat.u_format(o)) for i,o in \
64  
-        [("an_alias",    'get_ipython().system({u}"true ")'),     # alias
  64
+        [("an_alias",    "get_ipython().system({u}'true ')"),     # alias
65 65
          # Below: recursive aliases should expand whitespace-surrounded
66 66
          # chars, *not* initial chars which happen to be aliases:
67  
-         ("top",         'get_ipython().system({u}"d:/cygwin/top ")'),
  67
+         ("top",         "get_ipython().system({u}'d:/cygwin/top ')"),
68 68
          ]])
69 69
     ip.system = old_system_cmd
70 70
 
@@ -76,15 +76,15 @@ def test_handlers():
76 76
     # line.
77 77
     run([(i,py3compat.u_format(o)) for i,o in \
78 78
         [('"no change"', '"no change"'),             # normal
79  
-         ("!true",       'get_ipython().system({u}"true")'),      # shell_escapes
80  
-         ("!! true",     'get_ipython().magic({u}"sx  true")'),   # shell_escapes + magic
81  
-         ("!!true",      'get_ipython().magic({u}"sx true")'),    # shell_escapes + magic
82  
-         ("%lsmagic",    'get_ipython().magic({u}"lsmagic ")'),   # magic
83  
-         ("lsmagic",     'get_ipython().magic({u}"lsmagic ")'),   # magic
  79
+         (u"!true",       "get_ipython().system({u}'true')"),      # shell_escapes
  80
+         (u"!! true",     "get_ipython().magic({u}'sx  true')"),   # shell_escapes + magic
  81
+         (u"!!true",      "get_ipython().magic({u}'sx true')"),    # shell_escapes + magic
  82
+         (u"%lsmagic",    "get_ipython().magic({u}'lsmagic ')"),   # magic
  83
+         (u"lsmagic",     "get_ipython().magic({u}'lsmagic ')"),   # magic
84 84
          #("a = b # PYTHON-MODE", '_i'),          # emacs -- avoids _in cache
85 85
 
86 86
          # post-esc-char whitespace goes inside
87  
-         ("! true",   'get_ipython().system({u}" true")'),
  87
+         (u"! true",   "get_ipython().system({u}' true')"),
88 88
 
89 89
          # handle_help
90 90
 
@@ -99,19 +99,19 @@ def test_handlers():
99 99
     ip.prefilter_manager.multi_line_specials = False
100 100
     # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
101 101
     run([
102  
-        ('if 1:\n    !true',    'if 1:\n    !true'),
103  
-        ('if 1:\n    lsmagic',  'if 1:\n    lsmagic'),
104  
-        ('if 1:\n    an_alias', 'if 1:\n    an_alias'),
  102
+        (u'if 1:\n    !true',    u'if 1:\n    !true'),
  103
+        (u'if 1:\n    lsmagic',  u'if 1:\n    lsmagic'),
  104
+        (u'if 1:\n    an_alias', u'if 1:\n    an_alias'),
105 105
         ])
106 106
 
107 107
     ip.prefilter_manager.multi_line_specials = True
108 108
     # initial indents must be preserved.
109 109
     run([(i,py3compat.u_format(o)) for i,o in \
110  
-        [('if 1:\n    !true',    'if 1:\n    get_ipython().system({u}"true")'),
111  
-         ('if 2:\n    lsmagic',  'if 2:\n    get_ipython().magic({u}"lsmagic ")'),
112  
-         ('if 1:\n    an_alias', 'if 1:\n    get_ipython().system({u}"true ")'),
  110
+        [(u'if 1:\n    !true',    "if 1:\n    get_ipython().system({u}'true')"),
  111
+         (u'if 2:\n    lsmagic',  "if 2:\n    get_ipython().magic({u}'lsmagic ')"),
  112
+         (u'if 1:\n    an_alias', "if 1:\n    get_ipython().system({u}'true ')"),
113 113
          # Weird one
114  
-         ('if 1:\n    !!true',   'if 1:\n    get_ipython().magic({u}"sx true")'),
  114
+         (u'if 1:\n    !!true',   "if 1:\n    get_ipython().magic({u}'sx true')"),
115 115
 
116 116
          # Even with m_l_s on, autocall is off even with special chars
117 117
          ('if 1:\n    /fun 1 2', 'if 1:\n    /fun 1 2'),
62  IPython/core/tests/test_inputsplitter.py
@@ -405,16 +405,16 @@ def transform_checker(tests, func):
405 405
 syntax = \
406 406
   dict(assign_system =
407 407
        [(i,py3compat.u_format(o)) for i,o in \
408  
-       [('a =! ls', 'a = get_ipython().getoutput({u}"ls")'),
409  
-        ('b = !ls', 'b = get_ipython().getoutput({u}"ls")'),
  408
+       [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
  409
+        (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
410 410
         ('x=1', 'x=1'), # normal input is unmodified
411 411
         ('    ','    '),  # blank lines are kept intact
412 412
         ]],
413 413
 
414 414
        assign_magic =
415 415
        [(i,py3compat.u_format(o)) for i,o in \
416  
-       [('a =% who', 'a = get_ipython().magic({u}"who")'),
417  
-        ('b = %who', 'b = get_ipython().magic({u}"who")'),
  416
+       [(u'a =% who', "a = get_ipython().magic({u}'who')"),
  417
+        (u'b = %who', "b = get_ipython().magic({u}'who')"),
418 418
         ('x=1', 'x=1'), # normal input is unmodified
419 419
         ('    ','    '),  # blank lines are kept intact
420 420
         ]],
@@ -442,43 +442,45 @@ def transform_checker(tests, func):
442 442
        # System calls
443 443
        escaped_shell =
444 444
        [(i,py3compat.u_format(o)) for i,o in \
445  
-       [ ('!ls', 'get_ipython().system({u}"ls")'),
  445
+       [ (u'!ls', "get_ipython().system({u}'ls')"),
446 446
          # Double-escape shell, this means to capture the output of the
447 447
          # subprocess and return it
448  
-         ('!!ls', 'get_ipython().getoutput({u}"ls")'),
  448
+         (u'!!ls', "get_ipython().getoutput({u}'ls')"),
449 449
          ]],
450 450
 
451 451
        # Help/object info
452 452
        escaped_help =
453 453
        [(i,py3compat.u_format(o)) for i,o in \
454  
-       [ ('?', 'get_ipython().show_usage()'),
455  
-         ('?x1', 'get_ipython().magic({u}"pinfo x1")'),
456  
-         ('??x2', 'get_ipython().magic({u}"pinfo2 x2")'),
457  
-         ('?a.*s', 'get_ipython().magic({u}"psearch a.*s")'),
458  
-         ('?%hist', 'get_ipython().magic({u}"pinfo %hist")'),
459  
-         ('?abc = qwe', 'get_ipython().magic({u}"pinfo abc")'),
  454
+       [ (u'?', 'get_ipython().show_usage()'),
  455
+         (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
  456
+         (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
  457
+         (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
  458
+         (u'?%hist', "get_ipython().magic({u}'pinfo %hist')"),
  459
+         (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
460 460
          ]],
461 461
 
462 462
       end_help =
463 463
       [(i,py3compat.u_format(o)) for i,o in \
464  
-      [ ('x3?', 'get_ipython().magic({u}"pinfo x3")'),
465  
-        ('x4??', 'get_ipython().magic({u}"pinfo2 x4")'),
466  
-        ('%hist?', 'get_ipython().magic({u}"pinfo %hist")'),
467  
-        ('f*?', 'get_ipython().magic({u}"psearch f*")'),
468  
-        ('ax.*aspe*?', 'get_ipython().magic({u}"psearch ax.*aspe*")'),
469  
-        ('a = abc?', 'get_ipython().magic({u}"pinfo abc", next_input={u}"a = abc")'),
470  
-        ('a = abc.qe??', 'get_ipython().magic({u}"pinfo2 abc.qe", next_input={u}"a = abc.qe")'),
471  
-        ('a = *.items?', 'get_ipython().magic({u}"psearch *.items", next_input={u}"a = *.items")'),
472  
-        ('plot(a?', 'get_ipython().magic({u}"pinfo a", next_input={u}"plot(a")'),
473  
-        ('a*2 #comment?', 'a*2 #comment?'),
  464
+      [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
  465
+        (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
  466
+        (u'%hist?', "get_ipython().magic({u}'pinfo %hist')"),
  467
+        (u'f*?', "get_ipython().magic({u}'psearch f*')"),
  468
+        (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
  469
+        (u'a = abc?', "get_ipython().magic({u}'pinfo abc', next_input={u}'a = abc')"),
  470
+        (u'a = abc.qe??', "get_ipython().magic({u}'pinfo2 abc.qe', next_input={u}'a = abc.qe')"),
  471
+        (u'a = *.items?', "get_ipython().magic({u}'psearch *.items', next_input={u}'a = *.items')"),
  472
+        (u'plot(a?', "get_ipython().magic({u}'pinfo a', next_input={u}'plot(a')"),
  473
+        (u'a*2 #comment?', 'a*2 #comment?'),
474 474
         ]],
475 475
 
476 476
        # Explicit magic calls
477 477
        escaped_magic =
478 478
        [(i,py3compat.u_format(o)) for i,o in \
479  
-       [ ('%cd', 'get_ipython().magic({u}"cd")'),
480  
-         ('%cd /home', 'get_ipython().magic({u}"cd /home")'),
481  
-         ('    %magic', '    get_ipython().magic({u}"magic")'),
  479
+       [ (u'%cd', "get_ipython().magic({u}'cd')"),
  480
+         (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
  481
+         # Backslashes need to be escaped.
  482
+         (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
  483
+         (u'    %magic', "    get_ipython().magic({u}'magic')"),
482 484
          ]],
483 485
 
484 486
        # Quoting with separate arguments
@@ -508,11 +510,11 @@ def transform_checker(tests, func):
508 510
        # Check that we transform prompts before other transforms
509 511
        mixed =
510 512
        [(i,py3compat.u_format(o)) for i,o in \
511  
-       [ ('In [1]: %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
512  
-         ('>>> %lsmagic', 'get_ipython().magic({u}"lsmagic")'),
513  
-         ('In [2]: !ls', 'get_ipython().system({u}"ls")'),
514  
-         ('In [3]: abs?', 'get_ipython().magic({u}"pinfo abs")'),
515  
-         ('In [4]: b = %who', 'b = get_ipython().magic({u}"who")'),
  513
+       [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
  514
+         (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
  515
+         (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
  516
+         (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
  517
+         (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
516 518
          ]],
517 519
        )
518 520
 
34  IPython/utils/text.py
@@ -295,40 +295,6 @@ def esc_quotes(strng):
295 295
     return strng.replace('"','\\"').replace("'","\\'")
296 296
 
297 297
 
298  
-def make_quoted_expr(s):
299  
-    """Return string s in appropriate quotes, using raw string if possible.
300  
-
301  
-    XXX - example removed because it caused encoding errors in documentation
302  
-    generation.  We need a new example that doesn't contain invalid chars.
303  
-
304  
-    Note the use of raw string and padding at the end to allow trailing
305  
-    backslash.
306  
-    """
307  
-
308  
-    tail = ''
309  
-    tailpadding = ''
310  
-    raw  = ''
311  
-    ucode = '' if py3compat.PY3 else 'u'
312  
-    if "\\" in s:
313  
-        raw = 'r'
314  
-        if s.endswith('\\'):
315  
-            tail = '[:-1]'
316  
-            tailpadding = '_'
317  
-    if '"' not in s:
318  
-        quote = '"'
319  
-    elif "'" not in s:
320  
-        quote = "'"
321  
-    elif '"""' not in s and not s.endswith('"'):
322  
-        quote = '"""'
323  
-    elif "'''" not in s and not s.endswith("'"):
324  
-        quote = "'''"
325  
-    else:
326  
-        # give up, backslash-escaped string will do
327  
-        return '"%s"' % esc_quotes(s)
328  
-    res = ucode + raw + quote + s + tailpadding + quote + tail
329  
-    return res
330  
-
331  
-
332 298
 def qw(words,flat=0,sep=None,maxsplit=-1):
333 299
     """Similar to Perl's qw() operator, but with some more options.
334 300
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.