Repository: ipython/ipython

Issue:
Another strange input handling error
Getting this both on 0.12 and git master

```
In [1]: baz = None

In [2]: timeit foo = baz.groupby(lambda x: x.split('#')[0])
  File "<magic-timeit>", line 6
    foo = baz.groupby(lambda x: x.split('
                                        ^
SyntaxError: EOL while scanning string literal
```



Discussion:
I think this is due to the code trying to parse the command-line style syntax for magic functions. It has trouble when the argument to the magic command is Python code.


Resolving patch:
diff --git a/IPython/core/magic.py b/IPython/core/magic.py
--- a/IPython/core/magic.py
+++ b/IPython/core/magic.py
@@ -651,7 +651,7 @@ def magic_psearch(self, parameter_s=''):
         Options:
 
           -a: makes the pattern match even objects whose names start with a
-          single underscore.  These names are normally ommitted from the
+          single underscore.  These names are normally omitted from the
           search.
 
           -i/-c: make the pattern case insensitive/sensitive.  If neither of
@@ -661,7 +661,7 @@ def magic_psearch(self, parameter_s=''):
           internal default is to do a case sensitive search.
 
           -e/-s NAMESPACE: exclude/search a given namespace.  The pattern you
-          specifiy can be searched in any of the following namespaces:
+          specify can be searched in any of the following namespaces:
           'builtin', 'user', 'user_global','internal', 'alias', where
           'builtin' and 'user' are the search defaults.  Note that you should
           not use quotes when specifying namespaces.
@@ -683,7 +683,7 @@ def magic_psearch(self, parameter_s=''):
         %psearch r*.e*         -> objects that start with e in modules starting in r
         %psearch r*.* string   -> all strings in modules beginning with r
 
-        Case sensitve search:
+        Case sensitive search:
 
         %psearch -c a*         list all object beginning with lower case a
 
@@ -1144,7 +1144,7 @@ def magic_logstart(self,parameter_s=''):
         logger = self.shell.logger
 
         # if no args are given, the defaults set in the logger constructor by
-        # ipytohn remain valid
+        # ipython remain valid
         if par:
             try:
                 logfname,logmode = par.split()
@@ -1356,7 +1356,7 @@ def magic_prun(self, parameter_s ='',user_mode=1,
         file. The profile is still shown on screen.
 
         -D <filename>: save (via dump_stats) profile statistics to given
-        filename. This data is in a format understod by the pstats module, and
+        filename. This data is in a format understood by the pstats module, and
         is generated by a call to the dump_stats() method of profile
         objects. The profile is still shown on screen.
 
@@ -1551,7 +1551,7 @@ def magic_run(self, parameter_s ='', runner=None,
         something (not a comment or docstring) for it to stop execution.
 
         When the pdb debugger starts, you will see a (Pdb) prompt.  You must
-        first enter 'c' (without qoutes) to start execution up to the first
+        first enter 'c' (without quotes) to start execution up to the first
         breakpoint.
 
         Entering 'help' gives information about the use of the debugger.  You
@@ -2375,7 +2375,7 @@ def magic_edit(self,parameter_s='',last_call=['','']):
 
         Arguments:
 
-        If arguments are given, the following possibilites exist:
+        If arguments are given, the following possibilities exist:
 
         - If the argument is a filename, IPython will load that into the
           editor. It will execute its contents with execfile() when you exit,
@@ -2701,7 +2701,7 @@ def magic_rehashx(self, parameter_s = ''):
         This version explicitly checks that every entry in $PATH is a file
         with execute access (os.X_OK), so it is much slower than %rehash.
 
-        Under Windows, it checks executability as a match agains a
+        Under Windows, it checks executability as a match against a
         '|'-separated string of extensions, stored in the IPython config
         variable win_exec_ext.  This defaults to 'exe|com|bat'.
 
@@ -3066,7 +3066,7 @@ def magic_sc(self, parameter_s=''):
             146 setup.py
             130 win32_manual_post_install.py
 
-        Similiarly, the lists returned by the -l option are also special, in
+        Similarly, the lists returned by the -l option are also special, in
         the sense that you can equally invoke the .s attribute on them to
         automatically get a whitespace-separated string from their contents:
 
@@ -3078,7 +3078,7 @@ def magic_sc(self, parameter_s=''):
             In [9]: b.s
             Out[9]: 'setup.py win32_manual_post_install.py'
 
-        In summary, both the lists and strings used for ouptut capture have
+        In summary, both the lists and strings used for output capture have
         the following special attributes:
 
             .l (or .list) : value as list.
@@ -3093,7 +3093,7 @@ def magic_sc(self, parameter_s=''):
             # output, which uses shlex.split to strip options out.
             var,_ = args.split('=',1)
             var = var.strip()
-            # But the the command has to be extracted from the original input
+            # But the command has to be extracted from the original input
             # parameter_s, not on what parse_options returns, to avoid the
             # quote stripping which shlex.split performs on it.
             _,cmd = parameter_s.split('=',1)
@@ -3522,7 +3522,7 @@ def magic_precision(self, s=''):
         '-f', '--format',
         help='Convert an existing IPython notebook to a new format. This option '
              'specifies the new format and can have the values: xml, json, py. '
-             'The target filename is choosen automatically based on the new '
+             'The target filename is chosen automatically based on the new '
              'format. The filename argument gives the name of the source file.'
     )
     @magic_arguments.argument(
@@ -3591,7 +3591,7 @@ def magic_config(self, s):
         Examples
         --------
         
-        To see what classes are availabe for config, pass no arguments::
+        To see what classes are available for config, pass no arguments::
 
             In [1]: %config
             Available objects for config:
diff --git a/IPython/utils/_process_common.py b/IPython/utils/_process_common.py
--- a/IPython/utils/_process_common.py
+++ b/IPython/utils/_process_common.py
@@ -175,6 +175,7 @@ def arg_split(s, posix=False, strict=True):
     # and it shouldn't raise an exception.
     # It may be a bad idea to parse things that are not command-line args
     # through this function, but we do, so let's be safe about it.
+    lex.commenters='' #fix for GH-1269
     tokens = []
     while True:
         try:


Test patch:
diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py
--- a/IPython/core/tests/test_magic.py
+++ b/IPython/core/tests/test_magic.py
@@ -353,3 +353,8 @@ def test_timeit_shlex():
     _ip.magic('timeit -r1 -n1 ("a " + "b")')
     _ip.magic('timeit -r1 -n1 f("a " + "b")')
     _ip.magic('timeit -r1 -n1 f("a " + "b ")')
+
+
+def test_timeit_arguments():
+    "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
+    _ip.magic("timeit ('#')")