2181
2275
opt = config.Option('foo', default='bar')
2182
2276
self.assertEquals('bar', opt.get_default())
2278
def test_default_value_from_env(self):
2279
opt = config.Option('foo', default='bar', default_from_env=['FOO'])
2280
self.overrideEnv('FOO', 'quux')
2281
# Env variable provides a default taking over the option one
2282
self.assertEquals('quux', opt.get_default())
2284
def test_first_default_value_from_env_wins(self):
2285
opt = config.Option('foo', default='bar',
2286
default_from_env=['NO_VALUE', 'FOO', 'BAZ'])
2287
self.overrideEnv('FOO', 'foo')
2288
self.overrideEnv('BAZ', 'baz')
2289
# The first env var set wins
2290
self.assertEquals('foo', opt.get_default())
2292
def test_not_supported_list_default_value(self):
2293
self.assertRaises(AssertionError, config.Option, 'foo', default=[1])
2295
def test_not_supported_object_default_value(self):
2296
self.assertRaises(AssertionError, config.Option, 'foo',
2300
class TestOptionConverterMixin(object):
2302
def assertConverted(self, expected, opt, value):
2303
self.assertEquals(expected, opt.convert_from_unicode(value))
2305
def assertWarns(self, opt, value):
2308
warnings.append(args[0] % args[1:])
2309
self.overrideAttr(trace, 'warning', warning)
2310
self.assertEquals(None, opt.convert_from_unicode(value))
2311
self.assertLength(1, warnings)
2313
'Value "%s" is not valid for "%s"' % (value, opt.name),
2316
def assertErrors(self, opt, value):
2317
self.assertRaises(errors.ConfigOptionValueError,
2318
opt.convert_from_unicode, value)
2320
def assertConvertInvalid(self, opt, invalid_value):
2322
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2323
opt.invalid = 'warning'
2324
self.assertWarns(opt, invalid_value)
2325
opt.invalid = 'error'
2326
self.assertErrors(opt, invalid_value)
2329
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2331
def get_option(self):
2332
return config.Option('foo', help='A boolean.',
2333
from_unicode=config.bool_from_store)
2335
def test_convert_invalid(self):
2336
opt = self.get_option()
2337
# A string that is not recognized as a boolean
2338
self.assertConvertInvalid(opt, u'invalid-boolean')
2339
# A list of strings is never recognized as a boolean
2340
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2342
def test_convert_valid(self):
2343
opt = self.get_option()
2344
self.assertConverted(True, opt, u'True')
2345
self.assertConverted(True, opt, u'1')
2346
self.assertConverted(False, opt, u'False')
2349
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2351
def get_option(self):
2352
return config.Option('foo', help='An integer.',
2353
from_unicode=config.int_from_store)
2355
def test_convert_invalid(self):
2356
opt = self.get_option()
2357
# A string that is not recognized as an integer
2358
self.assertConvertInvalid(opt, u'forty-two')
2359
# A list of strings is never recognized as an integer
2360
self.assertConvertInvalid(opt, [u'a', u'list'])
2362
def test_convert_valid(self):
2363
opt = self.get_option()
2364
self.assertConverted(16, opt, u'16')
2366
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2368
def get_option(self):
2369
return config.Option('foo', help='A list.',
2370
from_unicode=config.list_from_store)
2372
def test_convert_invalid(self):
2373
# No string is invalid as all forms can be converted to a list
2376
def test_convert_valid(self):
2377
opt = self.get_option()
2378
# An empty string is an empty list
2379
self.assertConverted([], opt, '') # Using a bare str() just in case
2380
self.assertConverted([], opt, u'')
2382
self.assertConverted([u'True'], opt, u'True')
2384
self.assertConverted([u'42'], opt, u'42')
2386
self.assertConverted([u'bar'], opt, u'bar')
2387
# A list remains a list (configObj will turn a string containing commas
2388
# into a list, but that's not what we're testing here)
2389
self.assertConverted([u'foo', u'1', u'True'],
2390
opt, [u'foo', u'1', u'True'])
2393
class TestOptionConverterMixin(object):
2395
def assertConverted(self, expected, opt, value):
2396
self.assertEquals(expected, opt.convert_from_unicode(value))
2398
def assertWarns(self, opt, value):
2401
warnings.append(args[0] % args[1:])
2402
self.overrideAttr(trace, 'warning', warning)
2403
self.assertEquals(None, opt.convert_from_unicode(value))
2404
self.assertLength(1, warnings)
2406
'Value "%s" is not valid for "%s"' % (value, opt.name),
2409
def assertErrors(self, opt, value):
2410
self.assertRaises(errors.ConfigOptionValueError,
2411
opt.convert_from_unicode, value)
2413
def assertConvertInvalid(self, opt, invalid_value):
2415
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2416
opt.invalid = 'warning'
2417
self.assertWarns(opt, invalid_value)
2418
opt.invalid = 'error'
2419
self.assertErrors(opt, invalid_value)
2422
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2424
def get_option(self):
2425
return config.Option('foo', help='A boolean.',
2426
from_unicode=config.bool_from_store)
2428
def test_convert_invalid(self):
2429
opt = self.get_option()
2430
# A string that is not recognized as a boolean
2431
self.assertConvertInvalid(opt, u'invalid-boolean')
2432
# A list of strings is never recognized as a boolean
2433
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2435
def test_convert_valid(self):
2436
opt = self.get_option()
2437
self.assertConverted(True, opt, u'True')
2438
self.assertConverted(True, opt, u'1')
2439
self.assertConverted(False, opt, u'False')
2442
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2444
def get_option(self):
2445
return config.Option('foo', help='An integer.',
2446
from_unicode=config.int_from_store)
2448
def test_convert_invalid(self):
2449
opt = self.get_option()
2450
# A string that is not recognized as an integer
2451
self.assertConvertInvalid(opt, u'forty-two')
2452
# A list of strings is never recognized as an integer
2453
self.assertConvertInvalid(opt, [u'a', u'list'])
2455
def test_convert_valid(self):
2456
opt = self.get_option()
2457
self.assertConverted(16, opt, u'16')
2460
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2462
def get_option(self):
2463
return config.Option('foo', help='A list.',
2464
from_unicode=config.list_from_store)
2466
def test_convert_invalid(self):
2467
opt = self.get_option()
2468
# We don't even try to convert a list into a list, we only expect
2470
self.assertConvertInvalid(opt, [1])
2471
# No string is invalid as all forms can be converted to a list
2473
def test_convert_valid(self):
2474
opt = self.get_option()
2475
# An empty string is an empty list
2476
self.assertConverted([], opt, '') # Using a bare str() just in case
2477
self.assertConverted([], opt, u'')
2479
self.assertConverted([u'True'], opt, u'True')
2481
self.assertConverted([u'42'], opt, u'42')
2483
self.assertConverted([u'bar'], opt, u'bar')
2185
2486
class TestOptionRegistry(tests.TestCase):
2187
2488
def setUp(self):
2188
2489
super(TestOptionRegistry, self).setUp()
2189
2490
# Always start with an empty registry
2190
self.overrideAttr(config, 'option_registry', registry.Registry())
2491
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2191
2492
self.registry = config.option_registry
2193
2494
def test_register(self):
2194
2495
opt = config.Option('foo')
2195
self.registry.register('foo', opt)
2496
self.registry.register(opt)
2196
2497
self.assertIs(opt, self.registry.get('foo'))
2198
lazy_option = config.Option('lazy_foo')
2200
def test_register_lazy(self):
2201
self.registry.register_lazy('foo', self.__module__,
2202
'TestOptionRegistry.lazy_option')
2203
self.assertIs(self.lazy_option, self.registry.get('foo'))
2205
2499
def test_registered_help(self):
2206
opt = config.Option('foo')
2207
self.registry.register('foo', opt, help='A simple option')
2500
opt = config.Option('foo', help='A simple option')
2501
self.registry.register(opt)
2208
2502
self.assertEquals('A simple option', self.registry.get_help('foo'))
2504
lazy_option = config.Option('lazy_foo', help='Lazy help')
2506
def test_register_lazy(self):
2507
self.registry.register_lazy('lazy_foo', self.__module__,
2508
'TestOptionRegistry.lazy_option')
2509
self.assertIs(self.lazy_option, self.registry.get('lazy_foo'))
2511
def test_registered_lazy_help(self):
2512
self.registry.register_lazy('lazy_foo', self.__module__,
2513
'TestOptionRegistry.lazy_option')
2514
self.assertEquals('Lazy help', self.registry.get_help('lazy_foo'))
2211
2517
class TestRegisteredOptions(tests.TestCase):
2212
2518
"""All registered options should verify some constraints."""
2897
3326
class TestStackGet(TestStackWithTransport):
3329
super(TestStackGet, self).setUp()
3330
self.conf = self.get_stack(self)
2899
3332
def test_get_for_empty_stack(self):
2900
conf = self.get_stack(self)
2901
self.assertEquals(None, conf.get('foo'))
3333
self.assertEquals(None, self.conf.get('foo'))
2903
3335
def test_get_hook(self):
2904
conf = self.get_stack(self)
2905
conf.store._load_from_string('foo=bar')
3336
self.conf.store._load_from_string('foo=bar')
2907
3338
def hook(*args):
2908
3339
calls.append(args)
2909
3340
config.ConfigHooks.install_named_hook('get', hook, None)
2910
3341
self.assertLength(0, calls)
2911
value = conf.get('foo')
3342
value = self.conf.get('foo')
2912
3343
self.assertEquals('bar', value)
2913
3344
self.assertLength(1, calls)
2914
self.assertEquals((conf, 'foo', 'bar'), calls[0])
3345
self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
3348
class TestStackGetWithConverter(TestStackGet):
3351
super(TestStackGetWithConverter, self).setUp()
3352
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3353
self.registry = config.option_registry
3355
def register_bool_option(self, name, default=None, default_from_env=None):
3356
b = config.Option(name, help='A boolean.',
3357
default=default, default_from_env=default_from_env,
3358
from_unicode=config.bool_from_store)
3359
self.registry.register(b)
3361
def test_get_default_bool_None(self):
3362
self.register_bool_option('foo')
3363
self.assertEquals(None, self.conf.get('foo'))
3365
def test_get_default_bool_True(self):
3366
self.register_bool_option('foo', u'True')
3367
self.assertEquals(True, self.conf.get('foo'))
3369
def test_get_default_bool_False(self):
3370
self.register_bool_option('foo', False)
3371
self.assertEquals(False, self.conf.get('foo'))
3373
def test_get_default_bool_False_as_string(self):
3374
self.register_bool_option('foo', u'False')
3375
self.assertEquals(False, self.conf.get('foo'))
3377
def test_get_default_bool_from_env_converted(self):
3378
self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3379
self.overrideEnv('FOO', 'False')
3380
self.assertEquals(False, self.conf.get('foo'))
3382
def test_get_default_bool_when_conversion_fails(self):
3383
self.register_bool_option('foo', default='True')
3384
self.conf.store._load_from_string('foo=invalid boolean')
3385
self.assertEquals(True, self.conf.get('foo'))
3387
def register_integer_option(self, name,
3388
default=None, default_from_env=None):
3389
i = config.Option(name, help='An integer.',
3390
default=default, default_from_env=default_from_env,
3391
from_unicode=config.int_from_store)
3392
self.registry.register(i)
3394
def test_get_default_integer_None(self):
3395
self.register_integer_option('foo')
3396
self.assertEquals(None, self.conf.get('foo'))
3398
def test_get_default_integer(self):
3399
self.register_integer_option('foo', 42)
3400
self.assertEquals(42, self.conf.get('foo'))
3402
def test_get_default_integer_as_string(self):
3403
self.register_integer_option('foo', u'42')
3404
self.assertEquals(42, self.conf.get('foo'))
3406
def test_get_default_integer_from_env(self):
3407
self.register_integer_option('foo', default_from_env=['FOO'])
3408
self.overrideEnv('FOO', '18')
3409
self.assertEquals(18, self.conf.get('foo'))
3411
def test_get_default_integer_when_conversion_fails(self):
3412
self.register_integer_option('foo', default='12')
3413
self.conf.store._load_from_string('foo=invalid integer')
3414
self.assertEquals(12, self.conf.get('foo'))
3416
def register_list_option(self, name, default=None, default_from_env=None):
3417
l = config.Option(name, help='A list.',
3418
default=default, default_from_env=default_from_env,
3419
from_unicode=config.list_from_store)
3420
self.registry.register(l)
3422
def test_get_default_list_None(self):
3423
self.register_list_option('foo')
3424
self.assertEquals(None, self.conf.get('foo'))
3426
def test_get_default_list_empty(self):
3427
self.register_list_option('foo', '')
3428
self.assertEquals([], self.conf.get('foo'))
3430
def test_get_default_list_from_env(self):
3431
self.register_list_option('foo', default_from_env=['FOO'])
3432
self.overrideEnv('FOO', '')
3433
self.assertEquals([], self.conf.get('foo'))
3435
def test_get_with_list_converter_no_item(self):
3436
self.register_list_option('foo', None)
3437
self.conf.store._load_from_string('foo=,')
3438
self.assertEquals([], self.conf.get('foo'))
3440
def test_get_with_list_converter_many_items(self):
3441
self.register_list_option('foo', None)
3442
self.conf.store._load_from_string('foo=m,o,r,e')
3443
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3445
def test_get_with_list_converter_embedded_spaces_many_items(self):
3446
self.register_list_option('foo', None)
3447
self.conf.store._load_from_string('foo=" bar", "baz "')
3448
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3450
def test_get_with_list_converter_stripped_spaces_many_items(self):
3451
self.register_list_option('foo', None)
3452
self.conf.store._load_from_string('foo= bar , baz ')
3453
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3456
class TestStackExpandOptions(tests.TestCaseWithTransport):
3459
super(TestStackExpandOptions, self).setUp()
3460
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3461
self.registry = config.option_registry
3462
self.conf = build_branch_stack(self)
3464
def assertExpansion(self, expected, string, env=None):
3465
self.assertEquals(expected, self.conf.expand_options(string, env))
3467
def test_no_expansion(self):
3468
self.assertExpansion('foo', 'foo')
3470
def test_expand_default_value(self):
3471
self.conf.store._load_from_string('bar=baz')
3472
self.registry.register(config.Option('foo', default=u'{bar}'))
3473
self.assertEquals('baz', self.conf.get('foo', expand=True))
3475
def test_expand_default_from_env(self):
3476
self.conf.store._load_from_string('bar=baz')
3477
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3478
self.overrideEnv('FOO', '{bar}')
3479
self.assertEquals('baz', self.conf.get('foo', expand=True))
3481
def test_expand_default_on_failed_conversion(self):
3482
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3483
self.registry.register(
3484
config.Option('foo', default=u'{bar}',
3485
from_unicode=config.int_from_store))
3486
self.assertEquals(42, self.conf.get('foo', expand=True))
3488
def test_env_adding_options(self):
3489
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3491
def test_env_overriding_options(self):
3492
self.conf.store._load_from_string('foo=baz')
3493
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3495
def test_simple_ref(self):
3496
self.conf.store._load_from_string('foo=xxx')
3497
self.assertExpansion('xxx', '{foo}')
3499
def test_unknown_ref(self):
3500
self.assertRaises(errors.ExpandingUnknownOption,
3501
self.conf.expand_options, '{foo}')
3503
def test_indirect_ref(self):
3504
self.conf.store._load_from_string('''
3508
self.assertExpansion('xxx', '{bar}')
3510
def test_embedded_ref(self):
3511
self.conf.store._load_from_string('''
3515
self.assertExpansion('xxx', '{{bar}}')
3517
def test_simple_loop(self):
3518
self.conf.store._load_from_string('foo={foo}')
3519
self.assertRaises(errors.OptionExpansionLoop,
3520
self.conf.expand_options, '{foo}')
3522
def test_indirect_loop(self):
3523
self.conf.store._load_from_string('''
3527
e = self.assertRaises(errors.OptionExpansionLoop,
3528
self.conf.expand_options, '{foo}')
3529
self.assertEquals('foo->bar->baz', e.refs)
3530
self.assertEquals('{foo}', e.string)
3532
def test_list(self):
3533
self.conf.store._load_from_string('''
3537
list={foo},{bar},{baz}
3539
self.registry.register(
3540
config.Option('list', from_unicode=config.list_from_store))
3541
self.assertEquals(['start', 'middle', 'end'],
3542
self.conf.get('list', expand=True))
3544
def test_cascading_list(self):
3545
self.conf.store._load_from_string('''
3551
self.registry.register(
3552
config.Option('list', from_unicode=config.list_from_store))
3553
self.assertEquals(['start', 'middle', 'end'],
3554
self.conf.get('list', expand=True))
3556
def test_pathologically_hidden_list(self):
3557
self.conf.store._load_from_string('''
3563
hidden={start}{middle}{end}
3565
# What matters is what the registration says, the conversion happens
3566
# only after all expansions have been performed
3567
self.registry.register(
3568
config.Option('hidden', from_unicode=config.list_from_store))
3569
self.assertEquals(['bin', 'go'],
3570
self.conf.get('hidden', expand=True))
3573
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3576
super(TestStackCrossSectionsExpand, self).setUp()
3578
def get_config(self, location, string):
3581
# Since we don't save the config we won't strictly require to inherit
3582
# from TestCaseInTempDir, but an error occurs so quickly...
3583
c = config.LocationStack(location)
3584
c.store._load_from_string(string)
3587
def test_dont_cross_unrelated_section(self):
3588
c = self.get_config('/another/branch/path','''
3593
[/another/branch/path]
3596
self.assertRaises(errors.ExpandingUnknownOption,
3597
c.get, 'bar', expand=True)
3599
def test_cross_related_sections(self):
3600
c = self.get_config('/project/branch/path','''
3604
[/project/branch/path]
3607
self.assertEquals('quux', c.get('bar', expand=True))
2917
3610
class TestStackSet(TestStackWithTransport):