2199
2321
opt = config.Option('foo', default='bar')
2200
2322
self.assertEquals('bar', opt.get_default())
2324
def test_callable_default_value(self):
2325
def bar_as_unicode():
2327
opt = config.Option('foo', default=bar_as_unicode)
2328
self.assertEquals('bar', opt.get_default())
2330
def test_default_value_from_env(self):
2331
opt = config.Option('foo', default='bar', default_from_env=['FOO'])
2332
self.overrideEnv('FOO', 'quux')
2333
# Env variable provides a default taking over the option one
2334
self.assertEquals('quux', opt.get_default())
2336
def test_first_default_value_from_env_wins(self):
2337
opt = config.Option('foo', default='bar',
2338
default_from_env=['NO_VALUE', 'FOO', 'BAZ'])
2339
self.overrideEnv('FOO', 'foo')
2340
self.overrideEnv('BAZ', 'baz')
2341
# The first env var set wins
2342
self.assertEquals('foo', opt.get_default())
2344
def test_not_supported_list_default_value(self):
2345
self.assertRaises(AssertionError, config.Option, 'foo', default=[1])
2347
def test_not_supported_object_default_value(self):
2348
self.assertRaises(AssertionError, config.Option, 'foo',
2351
def test_not_supported_callable_default_value_not_unicode(self):
2352
def bar_not_unicode():
2354
opt = config.Option('foo', default=bar_not_unicode)
2355
self.assertRaises(AssertionError, opt.get_default)
2358
class TestOptionConverterMixin(object):
2360
def assertConverted(self, expected, opt, value):
2361
self.assertEquals(expected, opt.convert_from_unicode(value))
2363
def assertWarns(self, opt, value):
2366
warnings.append(args[0] % args[1:])
2367
self.overrideAttr(trace, 'warning', warning)
2368
self.assertEquals(None, opt.convert_from_unicode(value))
2369
self.assertLength(1, warnings)
2371
'Value "%s" is not valid for "%s"' % (value, opt.name),
2374
def assertErrors(self, opt, value):
2375
self.assertRaises(errors.ConfigOptionValueError,
2376
opt.convert_from_unicode, value)
2378
def assertConvertInvalid(self, opt, invalid_value):
2380
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2381
opt.invalid = 'warning'
2382
self.assertWarns(opt, invalid_value)
2383
opt.invalid = 'error'
2384
self.assertErrors(opt, invalid_value)
2387
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2389
def get_option(self):
2390
return config.Option('foo', help='A boolean.',
2391
from_unicode=config.bool_from_store)
2393
def test_convert_invalid(self):
2394
opt = self.get_option()
2395
# A string that is not recognized as a boolean
2396
self.assertConvertInvalid(opt, u'invalid-boolean')
2397
# A list of strings is never recognized as a boolean
2398
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2400
def test_convert_valid(self):
2401
opt = self.get_option()
2402
self.assertConverted(True, opt, u'True')
2403
self.assertConverted(True, opt, u'1')
2404
self.assertConverted(False, opt, u'False')
2407
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2409
def get_option(self):
2410
return config.Option('foo', help='An integer.',
2411
from_unicode=config.int_from_store)
2413
def test_convert_invalid(self):
2414
opt = self.get_option()
2415
# A string that is not recognized as an integer
2416
self.assertConvertInvalid(opt, u'forty-two')
2417
# A list of strings is never recognized as an integer
2418
self.assertConvertInvalid(opt, [u'a', u'list'])
2420
def test_convert_valid(self):
2421
opt = self.get_option()
2422
self.assertConverted(16, opt, u'16')
2425
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2427
def get_option(self):
2428
return config.Option('foo', help='A list.',
2429
from_unicode=config.list_from_store)
2431
def test_convert_invalid(self):
2432
# No string is invalid as all forms can be converted to a list
2435
def test_convert_valid(self):
2436
opt = self.get_option()
2437
# An empty string is an empty list
2438
self.assertConverted([], opt, '') # Using a bare str() just in case
2439
self.assertConverted([], opt, u'')
2441
self.assertConverted([u'True'], opt, u'True')
2443
self.assertConverted([u'42'], opt, u'42')
2445
self.assertConverted([u'bar'], opt, u'bar')
2446
# A list remains a list (configObj will turn a string containing commas
2447
# into a list, but that's not what we're testing here)
2448
self.assertConverted([u'foo', u'1', u'True'],
2449
opt, [u'foo', u'1', u'True'])
2452
class TestOptionConverterMixin(object):
2454
def assertConverted(self, expected, opt, value):
2455
self.assertEquals(expected, opt.convert_from_unicode(value))
2457
def assertWarns(self, opt, value):
2460
warnings.append(args[0] % args[1:])
2461
self.overrideAttr(trace, 'warning', warning)
2462
self.assertEquals(None, opt.convert_from_unicode(value))
2463
self.assertLength(1, warnings)
2465
'Value "%s" is not valid for "%s"' % (value, opt.name),
2468
def assertErrors(self, opt, value):
2469
self.assertRaises(errors.ConfigOptionValueError,
2470
opt.convert_from_unicode, value)
2472
def assertConvertInvalid(self, opt, invalid_value):
2474
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2475
opt.invalid = 'warning'
2476
self.assertWarns(opt, invalid_value)
2477
opt.invalid = 'error'
2478
self.assertErrors(opt, invalid_value)
2481
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2483
def get_option(self):
2484
return config.Option('foo', help='A boolean.',
2485
from_unicode=config.bool_from_store)
2487
def test_convert_invalid(self):
2488
opt = self.get_option()
2489
# A string that is not recognized as a boolean
2490
self.assertConvertInvalid(opt, u'invalid-boolean')
2491
# A list of strings is never recognized as a boolean
2492
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2494
def test_convert_valid(self):
2495
opt = self.get_option()
2496
self.assertConverted(True, opt, u'True')
2497
self.assertConverted(True, opt, u'1')
2498
self.assertConverted(False, opt, u'False')
2501
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2503
def get_option(self):
2504
return config.Option('foo', help='An integer.',
2505
from_unicode=config.int_from_store)
2507
def test_convert_invalid(self):
2508
opt = self.get_option()
2509
# A string that is not recognized as an integer
2510
self.assertConvertInvalid(opt, u'forty-two')
2511
# A list of strings is never recognized as an integer
2512
self.assertConvertInvalid(opt, [u'a', u'list'])
2514
def test_convert_valid(self):
2515
opt = self.get_option()
2516
self.assertConverted(16, opt, u'16')
2519
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2521
def get_option(self):
2522
return config.Option('foo', help='A list.',
2523
from_unicode=config.list_from_store)
2525
def test_convert_invalid(self):
2526
opt = self.get_option()
2527
# We don't even try to convert a list into a list, we only expect
2529
self.assertConvertInvalid(opt, [1])
2530
# No string is invalid as all forms can be converted to a list
2532
def test_convert_valid(self):
2533
opt = self.get_option()
2534
# An empty string is an empty list
2535
self.assertConverted([], opt, '') # Using a bare str() just in case
2536
self.assertConverted([], opt, u'')
2538
self.assertConverted([u'True'], opt, u'True')
2540
self.assertConverted([u'42'], opt, u'42')
2542
self.assertConverted([u'bar'], opt, u'bar')
2203
2545
class TestOptionRegistry(tests.TestCase):
2205
2547
def setUp(self):
2206
2548
super(TestOptionRegistry, self).setUp()
2207
2549
# Always start with an empty registry
2208
self.overrideAttr(config, 'option_registry', registry.Registry())
2550
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2209
2551
self.registry = config.option_registry
2211
2553
def test_register(self):
2212
2554
opt = config.Option('foo')
2213
self.registry.register('foo', opt)
2555
self.registry.register(opt)
2214
2556
self.assertIs(opt, self.registry.get('foo'))
2216
lazy_option = config.Option('lazy_foo')
2218
def test_register_lazy(self):
2219
self.registry.register_lazy('foo', self.__module__,
2220
'TestOptionRegistry.lazy_option')
2221
self.assertIs(self.lazy_option, self.registry.get('foo'))
2223
2558
def test_registered_help(self):
2224
opt = config.Option('foo')
2225
self.registry.register('foo', opt, help='A simple option')
2559
opt = config.Option('foo', help='A simple option')
2560
self.registry.register(opt)
2226
2561
self.assertEquals('A simple option', self.registry.get_help('foo'))
2563
lazy_option = config.Option('lazy_foo', help='Lazy help')
2565
def test_register_lazy(self):
2566
self.registry.register_lazy('lazy_foo', self.__module__,
2567
'TestOptionRegistry.lazy_option')
2568
self.assertIs(self.lazy_option, self.registry.get('lazy_foo'))
2570
def test_registered_lazy_help(self):
2571
self.registry.register_lazy('lazy_foo', self.__module__,
2572
'TestOptionRegistry.lazy_option')
2573
self.assertEquals('Lazy help', self.registry.get_help('lazy_foo'))
2229
2576
class TestRegisteredOptions(tests.TestCase):
2230
2577
"""All registered options should verify some constraints."""
2915
3392
class TestStackGet(TestStackWithTransport):
3395
super(TestStackGet, self).setUp()
3396
self.conf = self.get_stack(self)
2917
3398
def test_get_for_empty_stack(self):
2918
conf = self.get_stack(self)
2919
self.assertEquals(None, conf.get('foo'))
3399
self.assertEquals(None, self.conf.get('foo'))
2921
3401
def test_get_hook(self):
2922
conf = self.get_stack(self)
2923
conf.store._load_from_string('foo=bar')
3402
self.conf.set('foo', 'bar')
2925
3404
def hook(*args):
2926
3405
calls.append(args)
2927
3406
config.ConfigHooks.install_named_hook('get', hook, None)
2928
3407
self.assertLength(0, calls)
2929
value = conf.get('foo')
3408
value = self.conf.get('foo')
2930
3409
self.assertEquals('bar', value)
2931
3410
self.assertLength(1, calls)
2932
self.assertEquals((conf, 'foo', 'bar'), calls[0])
3411
self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
3414
class TestStackGetWithConverter(tests.TestCaseWithTransport):
3417
super(TestStackGetWithConverter, self).setUp()
3418
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3419
self.registry = config.option_registry
3420
# We just want a simple stack with a simple store so we can inject
3421
# whatever content the tests need without caring about what section
3422
# names are valid for a given store/stack.
3423
store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3424
self.conf = config.Stack([store.get_sections], store)
3426
def register_bool_option(self, name, default=None, default_from_env=None):
3427
b = config.Option(name, help='A boolean.',
3428
default=default, default_from_env=default_from_env,
3429
from_unicode=config.bool_from_store)
3430
self.registry.register(b)
3432
def test_get_default_bool_None(self):
3433
self.register_bool_option('foo')
3434
self.assertEquals(None, self.conf.get('foo'))
3436
def test_get_default_bool_True(self):
3437
self.register_bool_option('foo', u'True')
3438
self.assertEquals(True, self.conf.get('foo'))
3440
def test_get_default_bool_False(self):
3441
self.register_bool_option('foo', False)
3442
self.assertEquals(False, self.conf.get('foo'))
3444
def test_get_default_bool_False_as_string(self):
3445
self.register_bool_option('foo', u'False')
3446
self.assertEquals(False, self.conf.get('foo'))
3448
def test_get_default_bool_from_env_converted(self):
3449
self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3450
self.overrideEnv('FOO', 'False')
3451
self.assertEquals(False, self.conf.get('foo'))
3453
def test_get_default_bool_when_conversion_fails(self):
3454
self.register_bool_option('foo', default='True')
3455
self.conf.store._load_from_string('foo=invalid boolean')
3456
self.assertEquals(True, self.conf.get('foo'))
3458
def register_integer_option(self, name,
3459
default=None, default_from_env=None):
3460
i = config.Option(name, help='An integer.',
3461
default=default, default_from_env=default_from_env,
3462
from_unicode=config.int_from_store)
3463
self.registry.register(i)
3465
def test_get_default_integer_None(self):
3466
self.register_integer_option('foo')
3467
self.assertEquals(None, self.conf.get('foo'))
3469
def test_get_default_integer(self):
3470
self.register_integer_option('foo', 42)
3471
self.assertEquals(42, self.conf.get('foo'))
3473
def test_get_default_integer_as_string(self):
3474
self.register_integer_option('foo', u'42')
3475
self.assertEquals(42, self.conf.get('foo'))
3477
def test_get_default_integer_from_env(self):
3478
self.register_integer_option('foo', default_from_env=['FOO'])
3479
self.overrideEnv('FOO', '18')
3480
self.assertEquals(18, self.conf.get('foo'))
3482
def test_get_default_integer_when_conversion_fails(self):
3483
self.register_integer_option('foo', default='12')
3484
self.conf.store._load_from_string('foo=invalid integer')
3485
self.assertEquals(12, self.conf.get('foo'))
3487
def register_list_option(self, name, default=None, default_from_env=None):
3488
l = config.Option(name, help='A list.',
3489
default=default, default_from_env=default_from_env,
3490
from_unicode=config.list_from_store)
3491
self.registry.register(l)
3493
def test_get_default_list_None(self):
3494
self.register_list_option('foo')
3495
self.assertEquals(None, self.conf.get('foo'))
3497
def test_get_default_list_empty(self):
3498
self.register_list_option('foo', '')
3499
self.assertEquals([], self.conf.get('foo'))
3501
def test_get_default_list_from_env(self):
3502
self.register_list_option('foo', default_from_env=['FOO'])
3503
self.overrideEnv('FOO', '')
3504
self.assertEquals([], self.conf.get('foo'))
3506
def test_get_with_list_converter_no_item(self):
3507
self.register_list_option('foo', None)
3508
self.conf.store._load_from_string('foo=,')
3509
self.assertEquals([], self.conf.get('foo'))
3511
def test_get_with_list_converter_many_items(self):
3512
self.register_list_option('foo', None)
3513
self.conf.store._load_from_string('foo=m,o,r,e')
3514
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3516
def test_get_with_list_converter_embedded_spaces_many_items(self):
3517
self.register_list_option('foo', None)
3518
self.conf.store._load_from_string('foo=" bar", "baz "')
3519
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3521
def test_get_with_list_converter_stripped_spaces_many_items(self):
3522
self.register_list_option('foo', None)
3523
self.conf.store._load_from_string('foo= bar , baz ')
3524
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3527
class TestIterOptionRefs(tests.TestCase):
3528
"""iter_option_refs is a bit unusual, document some cases."""
3530
def assertRefs(self, expected, string):
3531
self.assertEquals(expected, list(config.iter_option_refs(string)))
3533
def test_empty(self):
3534
self.assertRefs([(False, '')], '')
3536
def test_no_refs(self):
3537
self.assertRefs([(False, 'foo bar')], 'foo bar')
3539
def test_single_ref(self):
3540
self.assertRefs([(False, ''), (True, '{foo}'), (False, '')], '{foo}')
3542
def test_broken_ref(self):
3543
self.assertRefs([(False, '{foo')], '{foo')
3545
def test_embedded_ref(self):
3546
self.assertRefs([(False, '{'), (True, '{foo}'), (False, '}')],
3549
def test_two_refs(self):
3550
self.assertRefs([(False, ''), (True, '{foo}'),
3551
(False, ''), (True, '{bar}'),
3555
def test_newline_in_refs_are_not_matched(self):
3556
self.assertRefs([(False, '{\nxx}{xx\n}{{\n}}')], '{\nxx}{xx\n}{{\n}}')
3559
class TestStackExpandOptions(tests.TestCaseWithTransport):
3562
super(TestStackExpandOptions, self).setUp()
3563
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3564
self.registry = config.option_registry
3565
self.conf = build_branch_stack(self)
3567
def assertExpansion(self, expected, string, env=None):
3568
self.assertEquals(expected, self.conf.expand_options(string, env))
3570
def test_no_expansion(self):
3571
self.assertExpansion('foo', 'foo')
3573
def test_expand_default_value(self):
3574
self.conf.store._load_from_string('bar=baz')
3575
self.registry.register(config.Option('foo', default=u'{bar}'))
3576
self.assertEquals('baz', self.conf.get('foo', expand=True))
3578
def test_expand_default_from_env(self):
3579
self.conf.store._load_from_string('bar=baz')
3580
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3581
self.overrideEnv('FOO', '{bar}')
3582
self.assertEquals('baz', self.conf.get('foo', expand=True))
3584
def test_expand_default_on_failed_conversion(self):
3585
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3586
self.registry.register(
3587
config.Option('foo', default=u'{bar}',
3588
from_unicode=config.int_from_store))
3589
self.assertEquals(42, self.conf.get('foo', expand=True))
3591
def test_env_adding_options(self):
3592
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3594
def test_env_overriding_options(self):
3595
self.conf.store._load_from_string('foo=baz')
3596
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3598
def test_simple_ref(self):
3599
self.conf.store._load_from_string('foo=xxx')
3600
self.assertExpansion('xxx', '{foo}')
3602
def test_unknown_ref(self):
3603
self.assertRaises(errors.ExpandingUnknownOption,
3604
self.conf.expand_options, '{foo}')
3606
def test_indirect_ref(self):
3607
self.conf.store._load_from_string('''
3611
self.assertExpansion('xxx', '{bar}')
3613
def test_embedded_ref(self):
3614
self.conf.store._load_from_string('''
3618
self.assertExpansion('xxx', '{{bar}}')
3620
def test_simple_loop(self):
3621
self.conf.store._load_from_string('foo={foo}')
3622
self.assertRaises(errors.OptionExpansionLoop,
3623
self.conf.expand_options, '{foo}')
3625
def test_indirect_loop(self):
3626
self.conf.store._load_from_string('''
3630
e = self.assertRaises(errors.OptionExpansionLoop,
3631
self.conf.expand_options, '{foo}')
3632
self.assertEquals('foo->bar->baz', e.refs)
3633
self.assertEquals('{foo}', e.string)
3635
def test_list(self):
3636
self.conf.store._load_from_string('''
3640
list={foo},{bar},{baz}
3642
self.registry.register(
3643
config.Option('list', from_unicode=config.list_from_store))
3644
self.assertEquals(['start', 'middle', 'end'],
3645
self.conf.get('list', expand=True))
3647
def test_cascading_list(self):
3648
self.conf.store._load_from_string('''
3654
self.registry.register(
3655
config.Option('list', from_unicode=config.list_from_store))
3656
self.assertEquals(['start', 'middle', 'end'],
3657
self.conf.get('list', expand=True))
3659
def test_pathologically_hidden_list(self):
3660
self.conf.store._load_from_string('''
3666
hidden={start}{middle}{end}
3668
# What matters is what the registration says, the conversion happens
3669
# only after all expansions have been performed
3670
self.registry.register(
3671
config.Option('hidden', from_unicode=config.list_from_store))
3672
self.assertEquals(['bin', 'go'],
3673
self.conf.get('hidden', expand=True))
3676
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3679
super(TestStackCrossSectionsExpand, self).setUp()
3681
def get_config(self, location, string):
3684
# Since we don't save the config we won't strictly require to inherit
3685
# from TestCaseInTempDir, but an error occurs so quickly...
3686
c = config.LocationStack(location)
3687
c.store._load_from_string(string)
3690
def test_dont_cross_unrelated_section(self):
3691
c = self.get_config('/another/branch/path','''
3696
[/another/branch/path]
3699
self.assertRaises(errors.ExpandingUnknownOption,
3700
c.get, 'bar', expand=True)
3702
def test_cross_related_sections(self):
3703
c = self.get_config('/project/branch/path','''
3707
[/project/branch/path]
3710
self.assertEquals('quux', c.get('bar', expand=True))
3713
class TestStackCrossStoresExpand(tests.TestCaseWithTransport):
3715
def test_cross_global_locations(self):
3716
l_store = config.LocationStore()
3717
l_store._load_from_string('''
3723
g_store = config.GlobalStore()
3724
g_store._load_from_string('''
3730
stack = config.LocationStack('/branch')
3731
self.assertEquals('glob-bar', stack.get('lbar', expand=True))
3732
self.assertEquals('loc-foo', stack.get('gfoo', expand=True))
3735
class TestStackExpandSectionLocals(tests.TestCaseWithTransport):
3737
def test_expand_locals_empty(self):
3738
l_store = config.LocationStore()
3739
l_store._load_from_string('''
3740
[/home/user/project]
3745
stack = config.LocationStack('/home/user/project/')
3746
self.assertEquals('', stack.get('base', expand=True))
3747
self.assertEquals('', stack.get('rel', expand=True))
3749
def test_expand_basename_locally(self):
3750
l_store = config.LocationStore()
3751
l_store._load_from_string('''
3752
[/home/user/project]
3756
stack = config.LocationStack('/home/user/project/branch')
3757
self.assertEquals('branch', stack.get('bfoo', expand=True))
3759
def test_expand_basename_locally_longer_path(self):
3760
l_store = config.LocationStore()
3761
l_store._load_from_string('''
3766
stack = config.LocationStack('/home/user/project/dir/branch')
3767
self.assertEquals('branch', stack.get('bfoo', expand=True))
3769
def test_expand_relpath_locally(self):
3770
l_store = config.LocationStore()
3771
l_store._load_from_string('''
3772
[/home/user/project]
3773
lfoo = loc-foo/{relpath}
3776
stack = config.LocationStack('/home/user/project/branch')
3777
self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
3779
def test_expand_relpath_unknonw_in_global(self):
3780
g_store = config.GlobalStore()
3781
g_store._load_from_string('''
3786
stack = config.LocationStack('/home/user/project/branch')
3787
self.assertRaises(errors.ExpandingUnknownOption,
3788
stack.get, 'gfoo', expand=True)
3790
def test_expand_local_option_locally(self):
3791
l_store = config.LocationStore()
3792
l_store._load_from_string('''
3793
[/home/user/project]
3794
lfoo = loc-foo/{relpath}
3798
g_store = config.GlobalStore()
3799
g_store._load_from_string('''
3805
stack = config.LocationStack('/home/user/project/branch')
3806
self.assertEquals('glob-bar', stack.get('lbar', expand=True))
3807
self.assertEquals('loc-foo/branch', stack.get('gfoo', expand=True))
3809
def test_locals_dont_leak(self):
3810
"""Make sure we chose the right local in presence of several sections.
3812
l_store = config.LocationStore()
3813
l_store._load_from_string('''
3815
lfoo = loc-foo/{relpath}
3816
[/home/user/project]
3817
lfoo = loc-foo/{relpath}
3820
stack = config.LocationStack('/home/user/project/branch')
3821
self.assertEquals('loc-foo/branch', stack.get('lfoo', expand=True))
3822
stack = config.LocationStack('/home/user/bar/baz')
3823
self.assertEquals('loc-foo/bar/baz', stack.get('lfoo', expand=True))
2935
3827
class TestStackSet(TestStackWithTransport):
2937
3829
def test_simple_set(self):
2938
3830
conf = self.get_stack(self)
2939
conf.store._load_from_string('foo=bar')
2940
self.assertEquals('bar', conf.get('foo'))
3831
self.assertEquals(None, conf.get('foo'))
2941
3832
conf.set('foo', 'baz')
2942
3833
# Did we get it back ?
2943
3834
self.assertEquals('baz', conf.get('foo'))