diff --git a/IPython/config/loader.py b/IPython/config/loader.py index 12752d0..196ed49 100644 --- a/IPython/config/loader.py +++ b/IPython/config/loader.py @@ -11,6 +11,7 @@ import os import re import sys import json +from ast import literal_eval from IPython.utils.path import filefind, get_ipython_dir from IPython.utils import py3compat @@ -487,7 +488,7 @@ class CommandLineConfigLoader(ConfigLoader): """execute self.config. = * expands ~ with expanduser - * tries to assign with raw eval, otherwise assigns with just the string, + * tries to assign with literal_eval, otherwise assigns with just the string, allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not* equivalent are `--C.a=4` and `--C.a='4'`. """ @@ -496,8 +497,8 @@ class CommandLineConfigLoader(ConfigLoader): # Try to see if regular Python syntax will work. This # won't handle strings as the quote marks are removed # by the system shell. - value = eval(rhs) - except (NameError, SyntaxError): + value = literal_eval(rhs) + except (NameError, SyntaxError, ValueError): # This case happens if the rhs is a string. value = rhs diff --git a/IPython/config/tests/test_loader.py b/IPython/config/tests/test_loader.py index a5fc91d..dc8f257 100644 --- a/IPython/config/tests/test_loader.py +++ b/IPython/config/tests/test_loader.py @@ -33,7 +33,7 @@ c = get_config() c.a=10 c.b=20 c.Foo.Bar.value=10 -c.Foo.Bam.value=list(range(10)) # list() is just so it's the same on Python 3 +c.Foo.Bam.value=list(range(10)) c.D.C.value='hi there' """ @@ -188,14 +188,23 @@ class TestArgParseCL(TestCase): class TestKeyValueCL(TestCase): klass = KeyValueConfigLoader + def test_eval(self): + cl = self.klass(log=log) + config = cl.load_config('--Class.str_trait=all --Class.int_trait=5 --Class.list_trait=["hello",5]'.split()) + self.assertEqual(config.Class.str_trait, 'all') + self.assertEqual(config.Class.int_trait, 5) + self.assertEqual(config.Class.list_trait, ["hello", 5]) + def test_basic(self): cl = self.klass(log=log) - argv = ['--'+s.strip('c.') for s in pyfile.split('\n')[2:-1]] + argv = [ '--' + s[2:] for s in pyfile.split('\n') if s.startswith('c.') ] + print(argv) config = cl.load_config(argv) self.assertEqual(config.a, 10) self.assertEqual(config.b, 20) self.assertEqual(config.Foo.Bar.value, 10) - self.assertEqual(config.Foo.Bam.value, list(range(10))) + # non-literal expressions are not evaluated + self.assertEqual(config.Foo.Bam.value, 'list(range(10))') self.assertEqual(config.D.C.value, 'hi there') def test_expanduser(self):