def defaults(preferences: Preferences): p = preferences profiles = p.profiles if preferences.is_in_profile('Appearance/__index__', profile='defaults'): if not preferences.get('Appearance/__index__', profile='defaults'): _theme_default(p) if 'Multimeter' not in profiles: multimeter_profile_default(p) p.profile = 'Multimeter' if 'Oscilloscope' not in profiles: oscilloscope_profile_default(p) if 'defaults' == p.profile: p.profile = 'Multimeter'
class TestPreferences(unittest.TestCase): def setUp(self): self.listener_calls = [] self.app = f'joulescope_preferences_{os.getpid()}' self.paths = paths.paths_current(app=self.app) os.makedirs(self.paths['dirs']['config']) self.p = Preferences(app=self.app) def tearDown(self): paths.clear(app=self.app, delete_data=True) def test_get_without_set_or_define(self): with self.assertRaises(KeyError): self.p.get('hello') with self.assertRaises(KeyError): self.p['hello'] def test_set_get_without_define(self): self.p.set('hello', 'world') self.assertEqual('world', self.p.get('hello')) def test_get_set_get(self): with self.assertRaises(KeyError): self.p.get('hello') self.assertEqual('default', self.p.get('hello', default='default')) self.p.set('hello', 'world') self.assertEqual('world', self.p.get('hello')) self.assertEqual('world', self.p.get('hello', default='default')) def test_contains(self): self.assertFalse('hello' in self.p) self.p['hello'] = 'world' self.assertTrue('hello' in self.p) def test_set_profile_missing(self): with self.assertRaises(KeyError): self.p.set('hello', 'world', profile='p1') def test_get_profile_missing(self): with self.assertRaises(KeyError): self.p.get('hello', profile='p1') def test_set_clear(self): self.p.set('hello', 'world') self.p.clear('hello') with self.assertRaises(KeyError): self.p.get('hello') def test_define_set_clear(self): self.p.define(name='hello', default='default') self.p.set('hello', 'world') self.p.clear('hello') self.assertEqual('default', self.p.get('hello')) def test_profile_add_remove(self): self.assertEqual(BASE_PROFILE, self.p.profile) self.assertEqual([BASE_PROFILE], self.p.profiles) self.p.profile_add('p1') self.assertEqual([BASE_PROFILE, 'p1'], self.p.profiles) self.assertEqual(BASE_PROFILE, self.p.profile) self.p.profile = 'p1' self.assertEqual('p1', self.p.profile) self.p.profile_remove('p1') self.assertEqual(BASE_PROFILE, self.p.profile) self.assertEqual([BASE_PROFILE], self.p.profiles) def test_profile_override(self): self.p.set('hello', 'all_value') self.assertEqual('all_value', self.p.get('hello')) self.p.profile_add('p1', activate=True) self.assertEqual('all_value', self.p.get('hello')) self.assertFalse(self.p.is_in_profile('hello')) self.p.set('hello', 'p1_value') self.assertTrue(self.p.is_in_profile('hello')) self.assertEqual('p1_value', self.p.get('hello')) self.p.profile = BASE_PROFILE self.assertEqual('all_value', self.p.get('hello')) def test_load_not_found(self): self.p.define(name='hello', default='world') self.assertEqual('world', self.p['hello']) self.p.load() self.assertEqual('world', self.p['hello']) def test_save_load_simple(self): self.p.set('hello', 'world') self.p.save() p = Preferences(app=self.app).load() self.assertEqual('world', p.get('hello')) def test_save_load_skip_starting_with_pound(self): self.p.set('hello/#there', 'world') self.assertIn('hello/#there', self.p) self.p.save() p = Preferences(app=self.app).load() self.assertNotIn('hello/#there', p) def test_save_load_bytes(self): self.p.set('hello', b'world') self.p.save() p = Preferences(app=self.app).load() self.assertEqual(b'world', p.get('hello')) def test_define_default_when_new(self): self.p.define(name='hello', default='world') self.assertEqual('world', self.p.get('hello')) def test_define_default_when_existing(self): self.p.set('hello', 'there') self.p.define(name='hello', default='world') self.assertEqual('there', self.p.get('hello')) def test_validate_str(self): self.assertEqual('there', validate('there', 'str')) with self.assertRaises(ValueError): validate(1, 'str') with self.assertRaises(ValueError): validate(1.0, 'str') with self.assertRaises(ValueError): validate([], 'str') with self.assertRaises(ValueError): validate({}, 'str') def test_validate_str_options_list(self): options = options_conform(['a', 'b', 'c']) self.assertEqual('a', validate('a', 'str', options=options)) with self.assertRaises(ValueError): validate('A', 'str', options=options) def test_validate_str_options_map(self): options = options_conform({ 'a': { 'brief': 'option a' }, 'b': { 'brief': 'option b' }, 'c': {} }) self.assertEqual('a', validate('a', 'str', options=options)) with self.assertRaises(ValueError): validate('A', 'str', options=options) def test_validate_str_options_map_with_aliases(self): options = options_conform( {'a': { 'brief': 'option a', 'aliases': ['b', 'c'] }}) self.assertEqual('a', validate('a', 'str', options=options)) self.assertEqual('a', validate('b', 'str', options=options)) self.assertEqual('a', validate('c', 'str', options=options)) with self.assertRaises(ValueError): validate('d', 'str', options=options) def test_options_callable_list(self): self.assertEqual('a', validate('a', 'str', options=lambda: ['a'])) with self.assertRaises(ValueError): validate('d', 'str', options=lambda: ['a']) def test_options_callable_dict(self): self.assertEqual('a', validate('a', 'str', options=lambda: {'a': 'a'})) with self.assertRaises(ValueError): validate('d', 'str', options=lambda: {'a': 'a'}) def test_validate_int(self): self.assertEqual(1, validate(1, 'int')) self.assertEqual(1, validate('1', 'int')) with self.assertRaises(ValueError): validate('world', 'int') def test_validate_int_range(self): options = {'min': 1, 'max': 11, 'step': 2} self.assertEqual(1, validate(1, 'int', options=options)) self.assertEqual(3, validate(3, 'int', options=options)) self.assertEqual(11, validate(11, 'int', options=options)) with self.assertRaises(ValueError): validate(-1, 'int', options=options) with self.assertRaises(ValueError): validate(2, 'int', options=options) with self.assertRaises(ValueError): validate(13, 'int', options=options) def test_validate_int_list(self): options = [6, 7, 8, 10, 12, 14, 16, 20, 24, 32, 40, 48, 64] self.assertEqual(10, validate(10, 'int', options=options)) self.assertEqual(10, validate('10', 'int', options=options)) with self.assertRaises(ValueError): self.assertEqual(10, validate(11, 'int', options=options)) def test_validate_float(self): self.assertEqual(1, validate(1, 'float')) self.assertEqual(1.1, validate(1.1, 'float')) self.assertEqual(1.1, validate('1.1', 'float')) with self.assertRaises(ValueError): validate('world', 'float') def test_validate_bool(self): self.assertEqual(True, validate(True, 'bool')) self.assertEqual(False, validate(False, 'bool')) self.assertEqual(False, validate(None, 'bool')) self.assertEqual(False, validate('off', 'bool')) self.assertEqual(False, validate('none', 'bool')) self.assertEqual(False, validate('None', 'bool')) self.assertEqual(False, validate('0', 'bool')) self.assertEqual(True, validate(1, 'bool')) self.assertEqual(True, validate('1.1', 'bool')) def test_validate_bytes(self): self.assertEqual(True, validate(b'12345', 'bytes')) def test_validate_dict(self): self.assertEqual({}, validate({}, 'dict')) with self.assertRaises(ValueError): validate('world', 'dict') def test_validate_none(self): self.assertEqual('hi', validate('hi', 'none')) def test_validate_color(self): self.assertEqual((1, 2, 3, 255), validate([1, 2, 3], 'color')) self.assertEqual((1, 2, 3, 4), validate([1, 2, 3, 4], 'color')) self.assertEqual((255, 0, 0, 255), validate('red', 'color')) with self.assertRaises(ValueError): validate('djflkajfdsfklsj', 'color') with self.assertRaises(ValueError): validate([1, 2], 'color') def test_validate_font(self): validate('Monospaced', 'font') def test_set_invalid_type(self): self.p.define(name='hello', dtype='str', default='world') with self.assertRaises(ValueError): self.p.set('hello', 1) def test_set_invalid_option(self): self.p.define(name='hello', dtype='str', options=['there', 'world'], default='world') self.p.set('hello', 'there') with self.assertRaises(ValueError): self.p.set('hello', 'you') def test_set_invalid_default(self): with self.assertRaises(ValueError): self.p.define(name='hello', dtype='str', options=['there', 'world'], default='bad') def test_definition_get(self): self.p.define(name='hello', dtype='str', default='world') d = self.p.definition_get(name='hello') def test_definitions_get(self): self.p.define(name='/', brief='top level', dtype='container') self.p.define(name='hello/', brief='holder', dtype='container') self.p.define(name='hello/world', brief='hello', dtype='str', default='world') self.p.define(name='hello/there/world', brief='hello', dtype='str', default='world') d = self.p.definitions self.assertEqual('/', d['name']) self.assertIn('children', d) self.assertEqual('hello/', d['children']['hello']['name']) self.assertEqual('hello/there/', d['children']['hello']['children']['there']['name']) def test_dict_style_access(self): p = self.p self.assertEqual(0, len(p)) p.define(name='hello/a', dtype='str', default='a_default') p.define(name='hello/b', dtype='str', default='b_default') self.assertEqual(2, len(p)) self.assertIn('hello/a', p) pairs = [(key, value) for key, value in p] self.assertEqual([('hello/a', 'a_default'), ('hello/b', 'b_default')], pairs) p.profile_add('p1', activate=True) p['hello/a'] = 'a_override' self.assertEqual('a_override', p['hello/a']) self.assertEqual('b_default', p['hello/b']) self.assertEqual(2, len(p)) del p['hello/a'] self.assertEqual(2, len(p)) self.assertEqual('a_default', p['hello/a']) def test_items(self): p = self.p p.define(name='a', dtype='str', default='zz') p.define(name='a/0', dtype='str', default='0') p.define(name='a/1', dtype='str', default='1') p.define(name='b/2', dtype='str', default='2') p.profile_add('p1', activate=True) p['a/1'] = 'new' self.assertEqual([('a', 'zz'), ('a/0', '0'), ('a/1', 'new'), ('b/2', '2')], list(p.items())) self.assertEqual([('a', 'zz'), ('a/0', '0'), ('a/1', 'new')], list(p.items(prefix='a'))) self.assertEqual([('a/0', '0'), ('a/1', 'new')], list(p.items(prefix='a/'))) self.assertEqual([('b/2', '2')], list(p.items(prefix='b/'))) def test_purge_single(self): self.p.define(name='a', dtype='str', default='zz') self.p.profile_add('p1', activate=True) self.p['a'] = '1' r = self.p.purge('a') self.assertEqual({ BASE_PROFILE: { 'a': 'zz' }, 'p1': { 'a': '1' } }, r['profiles']) with self.assertRaises(KeyError): self.p['a'] self.p.restore(r) self.assertEqual('1', self.p['a']) self.p.profile = BASE_PROFILE self.assertEqual('zz', self.p['a']) with self.assertRaises(ValueError): self.p['a'] = 1 def test_purge_hierarchy(self): p = self.p p.define(name='a/0', dtype='str', default='0') p.define(name='a/1', dtype='str', default='1') self.p.profile_add('p1', activate=True) self.p['a/0'] = '00' r = self.p.purge('a/') with self.assertRaises(KeyError): self.p['a/0'] self.p.restore(r) self.assertEqual('00', self.p['a/0']) self.p.profile = BASE_PROFILE self.assertEqual('0', self.p['a/0']) with self.assertRaises(ValueError): self.p['a/0'] = 1 def test_match(self): p = self.p p.define(name='a/0', dtype='str', default='0') p.define(name='a/1', dtype='str', default='1') self.assertEqual(['a/0', 'a/1'], p.match('a/')) self.assertEqual(['a/0'], p.match('a/0')) p.profile_add('p1', activate=True) self.assertEqual([], p.match('a/')) p['a/0'] = 'zz' self.assertEqual(['a/0'], p.match('a/')) def test_singleton(self): self.p.define(name='a', dtype='str', default='0', default_profile_only=True) self.p.profile_add('p', activate=True) self.p['a'] = 'override' self.assertEqual('override', self.p.get('a', profile='p')) self.assertEqual('override', self.p.get('a', profile=BASE_PROFILE)) def test_restore_base_default(self): self.p.define(name='a', dtype='str', default='0') self.p['a'] = 'base' self.p['b'] = 'no define' self.p.profile_add('p', activate=True) self.p['a'] = 'override' self.p.restore_base_defaults() self.assertEqual('override', self.p['a']) self.assertEqual('0', self.p.get('a', profile=BASE_PROFILE)) self.assertEqual('no define', self.p.get('b', profile=BASE_PROFILE))