2387
2388
opt, [u'foo', u'1', u'True'])
2391
class TestOptionConverterMixin(object):
2393
def assertConverted(self, expected, opt, value):
2394
self.assertEquals(expected, opt.convert_from_unicode(value))
2396
def assertWarns(self, opt, value):
2399
warnings.append(args[0] % args[1:])
2400
self.overrideAttr(trace, 'warning', warning)
2401
self.assertEquals(None, opt.convert_from_unicode(value))
2402
self.assertLength(1, warnings)
2404
'Value "%s" is not valid for "%s"' % (value, opt.name),
2407
def assertErrors(self, opt, value):
2408
self.assertRaises(errors.ConfigOptionValueError,
2409
opt.convert_from_unicode, value)
2411
def assertConvertInvalid(self, opt, invalid_value):
2413
self.assertEquals(None, opt.convert_from_unicode(invalid_value))
2414
opt.invalid = 'warning'
2415
self.assertWarns(opt, invalid_value)
2416
opt.invalid = 'error'
2417
self.assertErrors(opt, invalid_value)
2420
class TestOptionWithBooleanConverter(tests.TestCase, TestOptionConverterMixin):
2422
def get_option(self):
2423
return config.Option('foo', help='A boolean.',
2424
from_unicode=config.bool_from_store)
2426
def test_convert_invalid(self):
2427
opt = self.get_option()
2428
# A string that is not recognized as a boolean
2429
self.assertConvertInvalid(opt, u'invalid-boolean')
2430
# A list of strings is never recognized as a boolean
2431
self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2433
def test_convert_valid(self):
2434
opt = self.get_option()
2435
self.assertConverted(True, opt, u'True')
2436
self.assertConverted(True, opt, u'1')
2437
self.assertConverted(False, opt, u'False')
2440
class TestOptionWithIntegerConverter(tests.TestCase, TestOptionConverterMixin):
2442
def get_option(self):
2443
return config.Option('foo', help='An integer.',
2444
from_unicode=config.int_from_store)
2446
def test_convert_invalid(self):
2447
opt = self.get_option()
2448
# A string that is not recognized as an integer
2449
self.assertConvertInvalid(opt, u'forty-two')
2450
# A list of strings is never recognized as an integer
2451
self.assertConvertInvalid(opt, [u'a', u'list'])
2453
def test_convert_valid(self):
2454
opt = self.get_option()
2455
self.assertConverted(16, opt, u'16')
2458
class TestOptionWithListConverter(tests.TestCase, TestOptionConverterMixin):
2460
def get_option(self):
2461
return config.Option('foo', help='A list.',
2462
from_unicode=config.list_from_store)
2464
def test_convert_invalid(self):
2465
opt = self.get_option()
2466
# We don't even try to convert a list into a list, we only expect
2468
self.assertConvertInvalid(opt, [1])
2469
# No string is invalid as all forms can be converted to a list
2471
def test_convert_valid(self):
2472
opt = self.get_option()
2473
# An empty string is an empty list
2474
self.assertConverted([], opt, '') # Using a bare str() just in case
2475
self.assertConverted([], opt, u'')
2477
self.assertConverted([u'True'], opt, u'True')
2479
self.assertConverted([u'42'], opt, u'42')
2481
self.assertConverted([u'bar'], opt, u'bar')
2390
2484
class TestOptionRegistry(tests.TestCase):
2392
2486
def setUp(self):
3272
3368
self.conf.store._load_from_string('foo=m,o,r,e')
3273
3369
self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
3371
def test_get_with_list_converter_embedded_spaces_many_items(self):
3372
self.register_list_option('foo', None)
3373
self.conf.store._load_from_string('foo=" bar", "baz "')
3374
self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
3376
def test_get_with_list_converter_stripped_spaces_many_items(self):
3377
self.register_list_option('foo', None)
3378
self.conf.store._load_from_string('foo= bar , baz ')
3379
self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
3382
class TestStackExpandOptions(tests.TestCaseWithTransport):
3385
super(TestStackExpandOptions, self).setUp()
3386
self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3387
self.registry = config.option_registry
3388
self.conf = build_branch_stack(self)
3390
def assertExpansion(self, expected, string, env=None):
3391
self.assertEquals(expected, self.conf.expand_options(string, env))
3393
def test_no_expansion(self):
3394
self.assertExpansion('foo', 'foo')
3396
def test_expand_default_value(self):
3397
self.conf.store._load_from_string('bar=baz')
3398
self.registry.register(config.Option('foo', default=u'{bar}'))
3399
self.assertEquals('baz', self.conf.get('foo', expand=True))
3401
def test_expand_default_from_env(self):
3402
self.conf.store._load_from_string('bar=baz')
3403
self.registry.register(config.Option('foo', default_from_env=['FOO']))
3404
self.overrideEnv('FOO', '{bar}')
3405
self.assertEquals('baz', self.conf.get('foo', expand=True))
3407
def test_expand_default_on_failed_conversion(self):
3408
self.conf.store._load_from_string('baz=bogus\nbar=42\nfoo={baz}')
3409
self.registry.register(
3410
config.Option('foo', default=u'{bar}',
3411
from_unicode=config.int_from_store))
3412
self.assertEquals(42, self.conf.get('foo', expand=True))
3414
def test_env_adding_options(self):
3415
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3417
def test_env_overriding_options(self):
3418
self.conf.store._load_from_string('foo=baz')
3419
self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3421
def test_simple_ref(self):
3422
self.conf.store._load_from_string('foo=xxx')
3423
self.assertExpansion('xxx', '{foo}')
3425
def test_unknown_ref(self):
3426
self.assertRaises(errors.ExpandingUnknownOption,
3427
self.conf.expand_options, '{foo}')
3429
def test_indirect_ref(self):
3430
self.conf.store._load_from_string('''
3434
self.assertExpansion('xxx', '{bar}')
3436
def test_embedded_ref(self):
3437
self.conf.store._load_from_string('''
3441
self.assertExpansion('xxx', '{{bar}}')
3443
def test_simple_loop(self):
3444
self.conf.store._load_from_string('foo={foo}')
3445
self.assertRaises(errors.OptionExpansionLoop,
3446
self.conf.expand_options, '{foo}')
3448
def test_indirect_loop(self):
3449
self.conf.store._load_from_string('''
3453
e = self.assertRaises(errors.OptionExpansionLoop,
3454
self.conf.expand_options, '{foo}')
3455
self.assertEquals('foo->bar->baz', e.refs)
3456
self.assertEquals('{foo}', e.string)
3458
def test_list(self):
3459
self.conf.store._load_from_string('''
3463
list={foo},{bar},{baz}
3465
self.registry.register(
3466
config.Option('list', from_unicode=config.list_from_store))
3467
self.assertEquals(['start', 'middle', 'end'],
3468
self.conf.get('list', expand=True))
3470
def test_cascading_list(self):
3471
self.conf.store._load_from_string('''
3477
self.registry.register(
3478
config.Option('list', from_unicode=config.list_from_store))
3479
self.assertEquals(['start', 'middle', 'end'],
3480
self.conf.get('list', expand=True))
3482
def test_pathologically_hidden_list(self):
3483
self.conf.store._load_from_string('''
3489
hidden={start}{middle}{end}
3491
# What matters is what the registration says, the conversion happens
3492
# only after all expansions have been performed
3493
self.registry.register(
3494
config.Option('hidden', from_unicode=config.list_from_store))
3495
self.assertEquals(['bin', 'go'],
3496
self.conf.get('hidden', expand=True))
3499
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3502
super(TestStackCrossSectionsExpand, self).setUp()
3504
def get_config(self, location, string):
3507
# Since we don't save the config we won't strictly require to inherit
3508
# from TestCaseInTempDir, but an error occurs so quickly...
3509
c = config.LocationStack(location)
3510
c.store._load_from_string(string)
3513
def test_dont_cross_unrelated_section(self):
3514
c = self.get_config('/another/branch/path','''
3519
[/another/branch/path]
3522
self.assertRaises(errors.ExpandingUnknownOption,
3523
c.get, 'bar', expand=True)
3525
def test_cross_related_sections(self):
3526
c = self.get_config('/project/branch/path','''
3530
[/project/branch/path]
3533
self.assertEquals('quux', c.get('bar', expand=True))
3276
3536
class TestStackSet(TestStackWithTransport):