test_loader.py
419 lines
| 12.1 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2187 | # encoding: utf-8 | ||
Min RK
|
r19160 | """Tests for IPython.config.loader""" | ||
Brian Granger
|
r2187 | |||
Min RK
|
r19160 | # Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||||
Brian Granger
|
r2187 | |||
Min RK
|
r20703 | import copy | ||
import logging | ||||
Brian Granger
|
r2187 | import os | ||
MinRK
|
r13448 | import pickle | ||
MinRK
|
r4162 | import sys | ||
Matthias BUSSONNIER
|
r13771 | |||
Brian Granger
|
r2187 | from tempfile import mkstemp | ||
from unittest import TestCase | ||||
MinRK
|
r4162 | from nose import SkipTest | ||
Matthias BUSSONNIER
|
r13771 | import nose.tools as nt | ||
MinRK
|
r4162 | |||
MinRK
|
r4214 | |||
Brian Granger
|
r2245 | from IPython.config.loader import ( | ||
Config, | ||||
MinRK
|
r13470 | LazyConfigValue, | ||
Brian Granger
|
r3786 | PyFileConfigLoader, | ||
Matthias BUSSONNIER
|
r13771 | JSONFileConfigLoader, | ||
Brian Granger
|
r3786 | KeyValueConfigLoader, | ||
Brian Granger
|
r2245 | ArgParseConfigLoader, | ||
MinRK
|
r4830 | KVArgParseConfigLoader, | ||
MinRK
|
r13470 | ConfigError, | ||
Brian Granger
|
r2245 | ) | ||
Brian Granger
|
r2187 | |||
pyfile = """ | ||||
Fernando Perez
|
r2394 | c = get_config() | ||
Brian Granger
|
r3786 | c.a=10 | ||
c.b=20 | ||||
c.Foo.Bar.value=10 | ||||
Min RK
|
r20678 | c.Foo.Bam.value=list(range(10)) | ||
Brian Granger
|
r3786 | c.D.C.value='hi there' | ||
Brian Granger
|
r2187 | """ | ||
Matthias BUSSONNIER
|
r13771 | json1file = """ | ||
{ | ||||
"version": 1, | ||||
"a": 10, | ||||
"b": 20, | ||||
"Foo": { | ||||
"Bam": { | ||||
"value": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] | ||||
}, | ||||
"Bar": { | ||||
"value": 10 | ||||
} | ||||
}, | ||||
"D": { | ||||
"C": { | ||||
"value": "hi there" | ||||
} | ||||
} | ||||
} | ||||
""" | ||||
Brian Granger
|
r2187 | |||
Matthias BUSSONNIER
|
r13771 | # should not load | ||
json2file = """ | ||||
{ | ||||
"version": 2 | ||||
} | ||||
""" | ||||
import logging | ||||
log = logging.getLogger('devnull') | ||||
log.setLevel(0) | ||||
class TestFileCL(TestCase): | ||||
def _check_conf(self, config): | ||||
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))) | ||||
self.assertEqual(config.D.C.value, 'hi there') | ||||
def test_python(self): | ||||
Fernando Perez
|
r2392 | fd, fname = mkstemp('.py') | ||
Brian Granger
|
r2187 | f = os.fdopen(fd, 'w') | ||
f.write(pyfile) | ||||
f.close() | ||||
Brian Granger
|
r2198 | # Unlink the file | ||
Matthias BUSSONNIER
|
r13771 | cl = PyFileConfigLoader(fname, log=log) | ||
Brian Granger
|
r2187 | config = cl.load_config() | ||
Matthias BUSSONNIER
|
r13771 | self._check_conf(config) | ||
def test_json(self): | ||||
fd, fname = mkstemp('.json') | ||||
f = os.fdopen(fd, 'w') | ||||
f.write(json1file) | ||||
f.close() | ||||
# Unlink the file | ||||
cl = JSONFileConfigLoader(fname, log=log) | ||||
config = cl.load_config() | ||||
self._check_conf(config) | ||||
Min RK
|
r19160 | |||
def test_collision(self): | ||||
a = Config() | ||||
b = Config() | ||||
self.assertEqual(a.collisions(b), {}) | ||||
a.A.trait1 = 1 | ||||
b.A.trait2 = 2 | ||||
self.assertEqual(a.collisions(b), {}) | ||||
b.A.trait1 = 1 | ||||
self.assertEqual(a.collisions(b), {}) | ||||
b.A.trait1 = 0 | ||||
self.assertEqual(a.collisions(b), { | ||||
'A': { | ||||
'trait1': "1 ignored, using 0", | ||||
} | ||||
}) | ||||
self.assertEqual(b.collisions(a), { | ||||
'A': { | ||||
'trait1': "0 ignored, using 1", | ||||
} | ||||
}) | ||||
a.A.trait2 = 3 | ||||
self.assertEqual(b.collisions(a), { | ||||
'A': { | ||||
'trait1': "0 ignored, using 1", | ||||
'trait2': "2 ignored, using 3", | ||||
} | ||||
}) | ||||
Matthias BUSSONNIER
|
r13771 | |||
def test_v2raise(self): | ||||
fd, fname = mkstemp('.json') | ||||
f = os.fdopen(fd, 'w') | ||||
f.write(json2file) | ||||
f.close() | ||||
# Unlink the file | ||||
cl = JSONFileConfigLoader(fname, log=log) | ||||
with nt.assert_raises(ValueError): | ||||
cl.load_config() | ||||
Brian Granger
|
r2187 | |||
Brian Granger
|
r2501 | class MyLoader1(ArgParseConfigLoader): | ||
MinRK
|
r4606 | def _add_arguments(self, aliases=None, flags=None): | ||
Brian Granger
|
r2501 | p = self.parser | ||
p.add_argument('-f', '--foo', dest='Global.foo', type=str) | ||||
p.add_argument('-b', dest='MyClass.bar', type=int) | ||||
p.add_argument('-n', dest='n', action='store_true') | ||||
p.add_argument('Global.bam', type=str) | ||||
class MyLoader2(ArgParseConfigLoader): | ||||
MinRK
|
r4606 | def _add_arguments(self, aliases=None, flags=None): | ||
Brian Granger
|
r2501 | subparsers = self.parser.add_subparsers(dest='subparser_name') | ||
subparser1 = subparsers.add_parser('1') | ||||
subparser1.add_argument('-x',dest='Global.x') | ||||
subparser2 = subparsers.add_parser('2') | ||||
subparser2.add_argument('y') | ||||
Brian Granger
|
r2500 | |||
Brian Granger
|
r2187 | class TestArgParseCL(TestCase): | ||
def test_basic(self): | ||||
Brian Granger
|
r2501 | cl = MyLoader1() | ||
Brian Granger
|
r2187 | config = cl.load_config('-f hi -b 10 -n wow'.split()) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.Global.foo, 'hi') | ||
self.assertEqual(config.MyClass.bar, 10) | ||||
self.assertEqual(config.n, True) | ||||
self.assertEqual(config.Global.bam, 'wow') | ||||
Brian Granger
|
r2500 | config = cl.load_config(['wow']) | ||
Thomas Kluyver
|
r13374 | self.assertEqual(list(config.keys()), ['Global']) | ||
self.assertEqual(list(config.Global.keys()), ['bam']) | ||||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.Global.bam, 'wow') | ||
Brian Granger
|
r2187 | |||
def test_add_arguments(self): | ||||
Brian Granger
|
r2501 | cl = MyLoader2() | ||
Brian Granger
|
r2187 | config = cl.load_config('2 frobble'.split()) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.subparser_name, '2') | ||
self.assertEqual(config.y, 'frobble') | ||||
Brian Granger
|
r2187 | config = cl.load_config('1 -x frobble'.split()) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.subparser_name, '1') | ||
self.assertEqual(config.Global.x, 'frobble') | ||||
Brian Granger
|
r2245 | |||
Brian Granger
|
r2500 | def test_argv(self): | ||
Brian Granger
|
r2501 | cl = MyLoader1(argv='-f hi -b 10 -n wow'.split()) | ||
Brian Granger
|
r2500 | config = cl.load_config() | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.Global.foo, 'hi') | ||
self.assertEqual(config.MyClass.bar, 10) | ||||
self.assertEqual(config.n, True) | ||||
self.assertEqual(config.Global.bam, 'wow') | ||||
Brian Granger
|
r2500 | |||
Brian Granger
|
r3786 | class TestKeyValueCL(TestCase): | ||
MinRK
|
r4830 | klass = KeyValueConfigLoader | ||
Brian Granger
|
r3786 | |||
Min RK
|
r20678 | 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]) | ||||
Brian Granger
|
r3786 | def test_basic(self): | ||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
Min RK
|
r20678 | argv = [ '--' + s[2:] for s in pyfile.split('\n') if s.startswith('c.') ] | ||
print(argv) | ||||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(argv) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.a, 10) | ||
self.assertEqual(config.b, 20) | ||||
self.assertEqual(config.Foo.Bar.value, 10) | ||||
Min RK
|
r20678 | # non-literal expressions are not evaluated | ||
self.assertEqual(config.Foo.Bam.value, 'list(range(10))') | ||||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.D.C.value, 'hi there') | ||
MinRK
|
r3958 | |||
MinRK
|
r5189 | def test_expanduser(self): | ||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
MinRK
|
r5189 | argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"'] | ||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(argv) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.a, os.path.expanduser('~/1/2/3')) | ||
self.assertEqual(config.b, os.path.expanduser('~')) | ||||
self.assertEqual(config.c, os.path.expanduser('~/')) | ||||
self.assertEqual(config.d, '~/') | ||||
MinRK
|
r5189 | |||
MinRK
|
r3958 | def test_extra_args(self): | ||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
config = cl.load_config(['--a=5', 'b', '--c=10', 'd']) | ||||
Bradley M. Froehle
|
r7874 | self.assertEqual(cl.extra_args, ['b', 'd']) | ||
self.assertEqual(config.a, 5) | ||||
self.assertEqual(config.c, 10) | ||||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(['--', '--a=5', '--c=10']) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(cl.extra_args, ['--a=5', '--c=10']) | ||
MinRK
|
r4162 | |||
def test_unicode_args(self): | ||||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
MinRK
|
r4197 | argv = [u'--a=épsîlön'] | ||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(argv) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.a, u'épsîlön') | ||
MinRK
|
r4162 | |||
def test_unicode_bytes_args(self): | ||||
MinRK
|
r4197 | uarg = u'--a=é' | ||
MinRK
|
r4162 | try: | ||
barg = uarg.encode(sys.stdin.encoding) | ||||
except (TypeError, UnicodeEncodeError): | ||||
raise SkipTest("sys.stdin.encoding can't handle 'é'") | ||||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
config = cl.load_config([barg]) | ||||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.a, u'é') | ||
MinRK
|
r4830 | |||
def test_unicode_alias(self): | ||||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
MinRK
|
r4830 | argv = [u'--a=épsîlön'] | ||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(argv, aliases=dict(a='A.a')) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.A.a, u'épsîlön') | ||
MinRK
|
r4830 | |||
Brian Granger
|
r3786 | |||
MinRK
|
r4830 | class TestArgParseKVCL(TestKeyValueCL): | ||
klass = KVArgParseConfigLoader | ||||
Brian Granger
|
r3791 | |||
MinRK
|
r5189 | def test_expanduser2(self): | ||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
MinRK
|
r5189 | argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"] | ||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b')) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3')) | ||
self.assertEqual(config.A.b, '~/1/2/3') | ||||
MinRK
|
r5189 | |||
MinRK
|
r6757 | def test_eval(self): | ||
Matthias BUSSONNIER
|
r13771 | cl = self.klass(log=log) | ||
MinRK
|
r6757 | argv = ['-c', 'a=5'] | ||
Matthias BUSSONNIER
|
r13771 | config = cl.load_config(argv, aliases=dict(c='A.c')) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(config.A.c, u"a=5") | ||
MinRK
|
r6757 | |||
Brian Granger
|
r2245 | class TestConfig(TestCase): | ||
def test_setget(self): | ||||
c = Config() | ||||
c.a = 10 | ||||
Bradley M. Froehle
|
r7874 | self.assertEqual(c.a, 10) | ||
self.assertEqual('b' in c, False) | ||||
Brian Granger
|
r2245 | |||
def test_auto_section(self): | ||||
c = Config() | ||||
MinRK
|
r13470 | self.assertNotIn('A', c) | ||
assert not c._has_section('A') | ||||
Brian Granger
|
r2245 | A = c.A | ||
A.foo = 'hi there' | ||||
MinRK
|
r13470 | self.assertIn('A', c) | ||
assert c._has_section('A') | ||||
Bradley M. Froehle
|
r7874 | self.assertEqual(c.A.foo, 'hi there') | ||
Brian Granger
|
r2245 | del c.A | ||
MinRK
|
r13470 | self.assertEqual(c.A, Config()) | ||
Brian Granger
|
r2245 | |||
def test_merge_doesnt_exist(self): | ||||
c1 = Config() | ||||
c2 = Config() | ||||
c2.bar = 10 | ||||
c2.Foo.bar = 10 | ||||
MinRK
|
r10873 | c1.merge(c2) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(c1.Foo.bar, 10) | ||
self.assertEqual(c1.bar, 10) | ||||
Brian Granger
|
r2245 | c2.Bar.bar = 10 | ||
MinRK
|
r10873 | c1.merge(c2) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(c1.Bar.bar, 10) | ||
Brian Granger
|
r2245 | |||
def test_merge_exists(self): | ||||
c1 = Config() | ||||
c2 = Config() | ||||
c1.Foo.bar = 10 | ||||
c1.Foo.bam = 30 | ||||
c2.Foo.bar = 20 | ||||
c2.Foo.wow = 40 | ||||
MinRK
|
r10873 | c1.merge(c2) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(c1.Foo.bam, 30) | ||
self.assertEqual(c1.Foo.bar, 20) | ||||
self.assertEqual(c1.Foo.wow, 40) | ||||
Brian Granger
|
r2245 | c2.Foo.Bam.bam = 10 | ||
MinRK
|
r10873 | c1.merge(c2) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(c1.Foo.Bam.bam, 10) | ||
Brian Granger
|
r2245 | |||
def test_deepcopy(self): | ||||
c1 = Config() | ||||
c1.Foo.bar = 10 | ||||
c1.Foo.bam = 30 | ||||
c1.a = 'asdf' | ||||
c1.b = range(10) | ||||
Min RK
|
r20703 | c1.Test.logger = logging.Logger('test') | ||
c1.Test.get_logger = logging.getLogger('test') | ||||
Brian Granger
|
r2245 | c2 = copy.deepcopy(c1) | ||
Bradley M. Froehle
|
r7874 | self.assertEqual(c1, c2) | ||
Bradley M. Froehle
|
r7876 | self.assertTrue(c1 is not c2) | ||
self.assertTrue(c1.Foo is not c2.Foo) | ||||
Min RK
|
r20703 | self.assertTrue(c1.Test is not c2.Test) | ||
self.assertTrue(c1.Test.logger is c2.Test.logger) | ||||
self.assertTrue(c1.Test.get_logger is c2.Test.get_logger) | ||||
Brian Granger
|
r2245 | |||
def test_builtin(self): | ||||
c1 = Config() | ||||
MinRK
|
r11265 | c1.format = "json" | ||
MinRK
|
r10870 | |||
def test_fromdict(self): | ||||
c1 = Config({'Foo' : {'bar' : 1}}) | ||||
self.assertEqual(c1.Foo.__class__, Config) | ||||
self.assertEqual(c1.Foo.bar, 1) | ||||
MinRK
|
r10873 | def test_fromdictmerge(self): | ||
MinRK
|
r10870 | c1 = Config() | ||
c2 = Config({'Foo' : {'bar' : 1}}) | ||||
MinRK
|
r10873 | c1.merge(c2) | ||
MinRK
|
r10870 | self.assertEqual(c1.Foo.__class__, Config) | ||
self.assertEqual(c1.Foo.bar, 1) | ||||
MinRK
|
r10873 | def test_fromdictmerge2(self): | ||
MinRK
|
r10870 | c1 = Config({'Foo' : {'baz' : 2}}) | ||
c2 = Config({'Foo' : {'bar' : 1}}) | ||||
MinRK
|
r10873 | c1.merge(c2) | ||
MinRK
|
r10870 | self.assertEqual(c1.Foo.__class__, Config) | ||
self.assertEqual(c1.Foo.bar, 1) | ||||
self.assertEqual(c1.Foo.baz, 2) | ||||
MinRK
|
r12798 | self.assertNotIn('baz', c2.Foo) | ||
MinRK
|
r12929 | |||
def test_contains(self): | ||||
c1 = Config({'Foo' : {'baz' : 2}}) | ||||
c2 = Config({'Foo' : {'bar' : 1}}) | ||||
self.assertIn('Foo', c1) | ||||
self.assertIn('Foo.baz', c1) | ||||
self.assertIn('Foo.bar', c2) | ||||
self.assertNotIn('Foo.bar', c1) | ||||
MinRK
|
r13448 | def test_pickle_config(self): | ||
cfg = Config() | ||||
cfg.Foo.bar = 1 | ||||
pcfg = pickle.dumps(cfg) | ||||
cfg2 = pickle.loads(pcfg) | ||||
self.assertEqual(cfg2, cfg) | ||||
MinRK
|
r13470 | |||
def test_getattr_section(self): | ||||
cfg = Config() | ||||
self.assertNotIn('Foo', cfg) | ||||
Foo = cfg.Foo | ||||
assert isinstance(Foo, Config) | ||||
self.assertIn('Foo', cfg) | ||||
def test_getitem_section(self): | ||||
cfg = Config() | ||||
self.assertNotIn('Foo', cfg) | ||||
Foo = cfg['Foo'] | ||||
assert isinstance(Foo, Config) | ||||
self.assertIn('Foo', cfg) | ||||
def test_getattr_not_section(self): | ||||
cfg = Config() | ||||
self.assertNotIn('foo', cfg) | ||||
foo = cfg.foo | ||||
assert isinstance(foo, LazyConfigValue) | ||||
self.assertIn('foo', cfg) | ||||
MinRK
|
r15218 | def test_getattr_private_missing(self): | ||
cfg = Config() | ||||
self.assertNotIn('_repr_html_', cfg) | ||||
with self.assertRaises(AttributeError): | ||||
_ = cfg._repr_html_ | ||||
self.assertNotIn('_repr_html_', cfg) | ||||
self.assertEqual(len(cfg), 0) | ||||
MinRK
|
r13470 | def test_getitem_not_section(self): | ||
cfg = Config() | ||||
self.assertNotIn('foo', cfg) | ||||
foo = cfg['foo'] | ||||
assert isinstance(foo, LazyConfigValue) | ||||
self.assertIn('foo', cfg) | ||||
MinRK
|
r13471 | |||
def test_merge_copies(self): | ||||
c = Config() | ||||
c2 = Config() | ||||
c2.Foo.trait = [] | ||||
c.merge(c2) | ||||
c2.Foo.trait.append(1) | ||||
self.assertIsNot(c.Foo, c2.Foo) | ||||
self.assertEqual(c.Foo.trait, []) | ||||
self.assertEqual(c2.Foo.trait, [1]) | ||||
MinRK
|
r12929 | |||