2199
2275
opt = config.Option('foo', default='bar')
2200
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')
2203
2486
class TestOptionRegistry(tests.TestCase):
2205
2488
def setUp(self):
2206
2489
super(TestOptionRegistry, self).setUp()
2207
2490
# Always start with an empty registry
2208
self.overrideAttr(config, 'option_registry', registry.Registry())
2491
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
2209
2492
self.registry = config.option_registry
2211
2494
def test_register(self):
2212
2495
opt = config.Option('foo')
2213
self.registry.register('foo', opt)
2496
self.registry.register(opt)
2214
2497
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
2499
def test_registered_help(self):
2224
opt = config.Option('foo')
2225
self.registry.register('foo', opt, help='A simple option')
2500
opt = config.Option('foo', help='A simple option')
2501
self.registry.register(opt)
2226
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'))
2229
2517
class TestRegisteredOptions(tests.TestCase):
2230
2518
"""All registered options should verify some constraints."""
2915
3320
class TestStackGet(TestStackWithTransport):
3323
super(TestStackGet, self).setUp()
3324
self.conf = self.get_stack(self)
2917
3326
def test_get_for_empty_stack(self):
2918
conf = self.get_stack(self)
2919
self.assertEquals(None, conf.get('foo'))
3327
self.assertEquals(None, self.conf.get('foo'))
2921
3329
def test_get_hook(self):
2922
conf = self.get_stack(self)
2923
conf.store._load_from_string('foo=bar')
3330
self.conf.store._load_from_string('foo=bar')
2925
3332
def hook(*args):
2926
3333
calls.append(args)
2927
3334
config.ConfigHooks.install_named_hook('get', hook, None)
2928
3335
self.assertLength(0, calls)
2929
value = conf.get('foo')
3336
value = self.conf.get('foo')
2930
3337
self.assertEquals('bar', value)
2931
3338
self.assertLength(1, calls)
2932
self.assertEquals((conf, 'foo', 'bar'), calls[0])
3339
self.assertEquals((self.conf, 'foo', 'bar'), calls[0])
3342
class TestStackGetWithConverter(TestStackGet):
3345
super(TestStackGetWithConverter, self).setUp()
3346
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3347
self.registry = config.option_registry
3349
def register_bool_option(self, name, default=None, default_from_env=None):
3350
b = config.Option(name, help='A boolean.',
3351
default=default, default_from_env=default_from_env,
3352
from_unicode=config.bool_from_store)
3353
self.registry.register(b)
3355
def test_get_default_bool_None(self):
3356
self.register_bool_option('foo')
3357
self.assertEquals(None, self.conf.get('foo'))
3359
def test_get_default_bool_True(self):
3360
self.register_bool_option('foo', u'True')
3361
self.assertEquals(True, self.conf.get('foo'))
3363
def test_get_default_bool_False(self):
3364
self.register_bool_option('foo', False)
3365
self.assertEquals(False, self.conf.get('foo'))
3367
def test_get_default_bool_False_as_string(self):
3368
self.register_bool_option('foo', u'False')
3369
self.assertEquals(False, self.conf.get('foo'))
3371
def test_get_default_bool_from_env_converted(self):
3372
self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3373
self.overrideEnv('FOO', 'False')
3374
self.assertEquals(False, self.conf.get('foo'))
3376
def test_get_default_bool_when_conversion_fails(self):
3377
self.register_bool_option('foo', default='True')
3378
self.conf.store._load_from_string('foo=invalid boolean')
3379
self.assertEquals(True, self.conf.get('foo'))
3381
def register_integer_option(self, name,
3382
default=None, default_from_env=None):
3383
i = config.Option(name, help='An integer.',
3384
default=default, default_from_env=default_from_env,
3385
from_unicode=config.int_from_store)
3386
self.registry.register(i)
3388
def test_get_default_integer_None(self):
3389
self.register_integer_option('foo')
3390
self.assertEquals(None, self.conf.get('foo'))
3392
def test_get_default_integer(self):
3393
self.register_integer_option('foo', 42)
3394
self.assertEquals(42, self.conf.get('foo'))
3396
def test_get_default_integer_as_string(self):
3397
self.register_integer_option('foo', u'42')
3398
self.assertEquals(42, self.conf.get('foo'))
3400
def test_get_default_integer_from_env(self):
3401
self.register_integer_option('foo', default_from_env=['FOO'])
3402
self.overrideEnv('FOO', '18')
3403
self.assertEquals(18, self.conf.get('foo'))
3405
def test_get_default_integer_when_conversion_fails(self):
3406
self.register_integer_option('foo', default='12')
3407
self.conf.store._load_from_string('foo=invalid integer')
3408
self.assertEquals(12, self.conf.get('foo'))
3410
def register_list_option(self, name, default=None, default_from_env=None):
3411
l = config.Option(name, help='A list.',
3412
default=default, default_from_env=default_from_env,
3413
from_unicode=config.list_from_store)
3414
self.registry.register(l)
3416
def test_get_default_list_None(self):
3417
self.register_list_option('foo')
3418
self.assertEquals(None, self.conf.get('foo'))
3420
def test_get_default_list_empty(self):
3421
self.register_list_option('foo', '')
3422
self.assertEquals([], self.conf.get('foo'))
3424
def test_get_default_list_from_env(self):
3425
self.register_list_option('foo', default_from_env=['FOO'])
3426
self.overrideEnv('FOO', '')
3427
self.assertEquals([], self.conf.get('foo'))
3429
def test_get_with_list_converter_no_item(self):
3430
self.register_list_option('foo', None)
3431
self.conf.store._load_from_string('foo=,')
3432
self.assertEquals([], self.conf.get('foo'))
3434
def test_get_with_list_converter_many_items(self):
3435
self.register_list_option('foo', None)
3436
self.conf.store._load_from_string('foo=m,o,r,e')
3437
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3439
def test_get_with_list_converter_embedded_spaces_many_items(self):
3440
self.register_list_option('foo', None)
3441
self.conf.store._load_from_string('foo=" bar", "baz "')
3442
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3444
def test_get_with_list_converter_stripped_spaces_many_items(self):
3445
self.register_list_option('foo', None)
3446
self.conf.store._load_from_string('foo= bar , baz ')
3447
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3450
class TestStackExpandOptions(tests.TestCaseWithTransport):
3453
super(TestStackExpandOptions, self).setUp()
3454
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3455
self.registry = config.option_registry
3456
self.conf = build_branch_stack(self)
3458
def assertExpansion(self, expected, string, env=None):
3459
self.assertEquals(expected, self.conf.expand_options(string, env))
3461
def test_no_expansion(self):
3462
self.assertExpansion('foo', 'foo')
3464
def test_expand_default_value(self):
3465
self.conf.store._load_from_string('bar=baz')
3466
self.registry.register(config.Option('foo', default=u'{bar}'))
3467
self.assertEquals('baz', self.conf.get('foo', expand=True))
3469
def test_expand_default_from_env(self):
3470
self.conf.store._load_from_string('bar=baz')
3471
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3472
self.overrideEnv('FOO', '{bar}')
3473
self.assertEquals('baz', self.conf.get('foo', expand=True))
3475
def test_expand_default_on_failed_conversion(self):
3476
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3477
self.registry.register(
3478
config.Option('foo', default=u'{bar}',
3479
from_unicode=config.int_from_store))
3480
self.assertEquals(42, self.conf.get('foo', expand=True))
3482
def test_env_adding_options(self):
3483
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3485
def test_env_overriding_options(self):
3486
self.conf.store._load_from_string('foo=baz')
3487
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3489
def test_simple_ref(self):
3490
self.conf.store._load_from_string('foo=xxx')
3491
self.assertExpansion('xxx', '{foo}')
3493
def test_unknown_ref(self):
3494
self.assertRaises(errors.ExpandingUnknownOption,
3495
self.conf.expand_options, '{foo}')
3497
def test_indirect_ref(self):
3498
self.conf.store._load_from_string('''
3502
self.assertExpansion('xxx', '{bar}')
3504
def test_embedded_ref(self):
3505
self.conf.store._load_from_string('''
3509
self.assertExpansion('xxx', '{{bar}}')
3511
def test_simple_loop(self):
3512
self.conf.store._load_from_string('foo={foo}')
3513
self.assertRaises(errors.OptionExpansionLoop,
3514
self.conf.expand_options, '{foo}')
3516
def test_indirect_loop(self):
3517
self.conf.store._load_from_string('''
3521
e = self.assertRaises(errors.OptionExpansionLoop,
3522
self.conf.expand_options, '{foo}')
3523
self.assertEquals('foo->bar->baz', e.refs)
3524
self.assertEquals('{foo}', e.string)
3526
def test_list(self):
3527
self.conf.store._load_from_string('''
3531
list={foo},{bar},{baz}
3533
self.registry.register(
3534
config.Option('list', from_unicode=config.list_from_store))
3535
self.assertEquals(['start', 'middle', 'end'],
3536
self.conf.get('list', expand=True))
3538
def test_cascading_list(self):
3539
self.conf.store._load_from_string('''
3545
self.registry.register(
3546
config.Option('list', from_unicode=config.list_from_store))
3547
self.assertEquals(['start', 'middle', 'end'],
3548
self.conf.get('list', expand=True))
3550
def test_pathologically_hidden_list(self):
3551
self.conf.store._load_from_string('''
3557
hidden={start}{middle}{end}
3559
# What matters is what the registration says, the conversion happens
3560
# only after all expansions have been performed
3561
self.registry.register(
3562
config.Option('hidden', from_unicode=config.list_from_store))
3563
self.assertEquals(['bin', 'go'],
3564
self.conf.get('hidden', expand=True))
3567
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3570
super(TestStackCrossSectionsExpand, self).setUp()
3572
def get_config(self, location, string):
3575
# Since we don't save the config we won't strictly require to inherit
3576
# from TestCaseInTempDir, but an error occurs so quickly...
3577
c = config.LocationStack(location)
3578
c.store._load_from_string(string)
3581
def test_dont_cross_unrelated_section(self):
3582
c = self.get_config('/another/branch/path','''
3587
[/another/branch/path]
3590
self.assertRaises(errors.ExpandingUnknownOption,
3591
c.get, 'bar', expand=True)
3593
def test_cross_related_sections(self):
3594
c = self.get_config('/project/branch/path','''
3598
[/project/branch/path]
3601
self.assertEquals('quux', c.get('bar', expand=True))
2935
3604
class TestStackSet(TestStackWithTransport):