def test_write_an_inverse_bool_entry(self): meta_config = { 'a_bool': { 'entry': 'an.example', 'type': 'inverse-bool', 'default': False } } self._tested.set_meta_config(meta_config) config = IniConfig() self._tested.write(dict(), config) self.assert_equal( 'the-default-value', config.get_or_default_value('an', 'example', 'the-default-value')) self._tested.write(dict(a_bool=False), config) self.assert_equal( 'yes', config.get_or_default_value('an', 'example', 'unexpected-default-value')) self._tested.write(dict(a_bool=True), config) self.assert_equal( 'no', config.get_or_default_value('an', 'example', 'unexpected-default-value'))
def __load_inverse_bool_item(self, meta_config_entry: typing.Dict, config: IniConfig): section, option = self._get_section_option(meta_config_entry) if not config.has(section, option): return meta_config_entry['default'] else: value = config.get(section, option) return not convert_to_bool(value)
def test_config_cannot_be_opened_twice_without_close(self): cfg = IniConfig() cfg.open(f'{ASSETS_DIR}/1.ini') self.assert_raises(IniConfigError, cfg.open, f'{ASSETS_DIR}/2.ini') cfg.close() cfg.open(f'{ASSETS_DIR}/2.ini') self.assert_equal({'more': {'stuff': '4444'}}, cfg.as_dict()) self.assert_equal(f'{ASSETS_DIR}/2.ini', cfg.config_file) self.assert_equal([f'{ASSETS_DIR}/2.ini'], cfg.loaded_files)
def test_write_a_string_entry_which_is_not_set(self): meta_config = { 'sample_text': { 'entry': 'an.example', 'type': 'string', 'default': 'something' } } self._tested.set_meta_config(meta_config) config = IniConfig() self._tested.write(dict(), config) self.assert_equal( 'the-default-value', config.get_or_default_value('an', 'example', 'the-default-value'))
def test_load_an_int_entry(self): meta_config = { 'an_int': { 'entry': 'an.example', 'type': 'int', 'default': 42 } } self._tested.set_meta_config(meta_config) config = IniConfig() self.assert_equal(dict(an_int=42), self._tested.load(config)) config.set('an', 'example', '33') self.assert_equal(dict(an_int=33), self._tested.load(config))
def test_open_sets_and_close_clears_config_and_filename(self): cfg = IniConfig() cfg.open(f'{ASSETS_DIR}/1.ini') self.assert_equal({'some': {'thing': 'some value'}}, cfg.as_dict()) self.assert_equal(f'{ASSETS_DIR}/1.ini', cfg.config_file) self.assert_equal([f'{ASSETS_DIR}/1.ini'], cfg.loaded_files) cfg.close() self.assert_equal({}, cfg.as_dict()) self.assert_is_none(cfg.config_file) self.assert_equal([], cfg.loaded_files)
def test_load_a_string_entry(self): meta_config = { 'sample_text': { 'entry': 'an.example', 'type': 'string', 'default': 'something' } } self._tested.set_meta_config(meta_config) config = IniConfig() self.assert_equal(dict(sample_text='something'), self._tested.load(config)) config.set('an', 'example', 'some text') self.assert_equal(dict(sample_text='some text'), self._tested.load(config))
def test_config_can_be_extended_by_multiple_ini_files(self): cfg = IniConfig() cfg.open(f'{ASSETS_DIR}/1.ini') self.assert_equal(f'{ASSETS_DIR}/1.ini', cfg.config_file) self.assert_equal([f'{ASSETS_DIR}/1.ini'], cfg.loaded_files) self.assert_equal({'some': {'thing': 'some value'}}, cfg.as_dict()) cfg.open(f'{ASSETS_DIR}/2.ini', merge=True) self.assert_equal(f'{ASSETS_DIR}/1.ini', cfg.config_file) self.assert_equal([f'{ASSETS_DIR}/{x}.ini' for x in range(1, 3)], cfg.loaded_files) self.assert_equal({'more': {'stuff': '4444'}, 'some': {'thing': 'some value'}}, cfg.as_dict()) cfg.open(f'{ASSETS_DIR}/3.ini', merge=True) self.assert_equal(f'{ASSETS_DIR}/1.ini', cfg.config_file) self.assert_equal([f'{ASSETS_DIR}/{x}.ini' for x in range(1, 4)], cfg.loaded_files) self.assert_equal( {'some': {'thing': 'some value', 'thingy': 'multi\nline stuff'}, 'more': {'stuff': 'more.stuff.!\\nx'}}, cfg.as_dict())
def test_write_an_int_entry(self): meta_config = { 'an_int': { 'entry': 'an.example', 'type': 'int', 'default': 42 } } self._tested.set_meta_config(meta_config) config = IniConfig() self._tested.write(dict(), config) self.assert_equal( 'the-default-value', config.get_or_default_value('an', 'example', 'the-default-value')) self._tested.write(dict(an_int=45), config) self.assert_equal( '45', config.get_or_default_value('an', 'example', 'unexpected-default-value'))
def test_overwrite_and_delete(self): # Saving because the order of test functions is not guaranteed saved_settings = list(self.settings) # Test assumes it self.assert_false(os.path.exists(self.cfg_file)) cfg = IniConfig() cfg.open(self.cfg_file) for (section, option, value) in self.settings: cfg.set(section, option, value) self._verify_config(cfg) self.settings[0][2] += " Something not too useful" cfg.set(self.settings[0][0], self.settings[0][1], self.settings[0][2]) self._verify_config(cfg) cfg.remove(self.settings[1][0], self.settings[1][1]) del self.settings[1] self._verify_config(cfg) self.settings = saved_settings
def test_load_nodes(self): meta_config = { 'a_bool': { 'entry': 'an.example', 'type': 'inverse-bool', 'default': False }, 'a_node': { 'type': 'node', 'an_int': { 'entry': 'an.int_entry', 'type': 'int', 'default': 0 }, 'another_node': { 'type': 'node', 'a_string': { 'entry': 'a.string', 'type': 'string', 'default': 'default string-value' }, } } } self._tested.set_meta_config(meta_config) config = IniConfig() config.set('an', 'example', 'no') config.set('an', 'int_entry', '42') self.assert_equal( dict(a_bool=True, a_node=dict( an_int=42, another_node=dict(a_string='default string-value'))), self._tested.load(config))
def _get_core_and_custom_version(project_dir: str) -> typing.Tuple[str, str]: cfg = IniConfig() cfg.open(os.path.join(project_dir, Project.CFG_FILE)) core_version = cfg.get('core', 'version') custom_version = cfg.get_or_default_value('core', 'custom_version', INITIAL_VERSION) return core_version, custom_version
def test_write_nodes(self): meta_config = { 'a_bool': { 'entry': 'an.example', 'type': 'inverse-bool', 'default': False }, 'a_node': { 'type': 'node', 'an_int': { 'entry': 'an.int_entry', 'type': 'int', 'default': 0 }, 'another_node': { 'type': 'node', 'a_string': { 'entry': 'a.string', 'type': 'string', 'default': 'default string-value' }, } } } self._tested.set_meta_config(meta_config) config = IniConfig() self._tested.write(dict(), config) self.assert_equal( 'the-default-value', config.get_or_default_value('an', 'example', 'the-default-value')) self._tested.write( dict(a_bool=False, a_node=dict(another_node=dict(a_string='some_value'))), config) self.assert_equal( 'yes', config.get_or_default_value('an', 'example', 'unexpected-default-value')) self.assert_equal( 'the-default-value', config.get_or_default_value('an', 'int_entry', 'the-default-value')) self.assert_equal( 'some_value', config.get_or_default_value('a', 'string', 'unexpected-default-value'))
def test_load_an_inverse_bool_entry(self): meta_config = { 'a_bool': { 'entry': 'an.example', 'type': 'inverse-bool', 'default': False } } self._tested.set_meta_config(meta_config) config = IniConfig() self.assert_equal(dict(a_bool=False), self._tested.load(config)) config.set('an', 'example', 'no') self.assert_equal(dict(a_bool=True), self._tested.load(config)) config.set('an', 'example', 'yes') self.assert_equal(dict(a_bool=False), self._tested.load(config))
def test_cfg_init(self): cfg = IniConfig() self.assert_is_none(cfg.config_file) self.assert_is_not_none(cfg.parser)
def test_config_can_be_written_and_read(self): (fd, filename) = tempfile.mkstemp() os.close(fd) cfg = IniConfig() cfg.set('an', 'example', '4222222') cfg.write(filename) cfg = IniConfig() self.assert_is_none(cfg.get('an', 'example')) cfg.open(filename) self.assert_equal('4222222', cfg.get('an', 'example')) os.unlink(filename)
def __write_int_entry(self, meta_config_entry: typing.Dict, new_config, config: IniConfig): section, option = self._get_section_option(meta_config_entry) config.set(section, option, str(new_config))
class Project: CFG_FILE = 'project.cfg' VERSION = 2 def __init__(self, name: str): self.name = name self._project_dir = f'{app_config().projectdir}/{name}' self.config = IniConfig() self.config.open(f'{self._project_dir}/{self.CFG_FILE}') self.ext = _project_ext_type(self) if _project_ext_type else None @property def project_dir(self) -> str: return self._project_dir @property def etc_dir(self) -> str: return f'{self._project_dir}/etc' @property def src_dir(self) -> str: return f'{self._project_dir}/src' @property def tmp_dir(self) -> str: return f'{self._project_dir}/tmp' @property def branch(self) -> str: return self.config.get('main', 'branch') @property def upstream_branch(self) -> str: return self.config.get('main', 'upstream_branch') @property def remote(self) -> str: return self.config.get('main', 'remote') @property def ticket_id(self) -> str: return self.config.get('main', 'ticket_id') def repo_dir(self, repo: str) -> str: return f'{self.src_dir}/{repo}' @property def repositories(self) -> typing.Iterable[str]: for entry in os.listdir(self.src_dir): if os.path.exists(f'{self.repo_dir(entry)}/.git'): yield entry @property def version(self) -> str: return self.config.get('core', 'version') @property def custom_version(self) -> str: return self.config.get_or_default_value('core', 'custom_version', INITIAL_VERSION) def as_dict(self) -> typing.Dict[str, typing.Any]: return dict(name=self.name, branch=self.branch, upstream=dict(remote=self.remote, branch=self.upstream_branch), ticket_id=self.ticket_id, repositories=list(self.repositories))
def test_write_without_open_and_filename_fails(self): cfg = IniConfig() self.assert_raises(IniConfigError, cfg.write)
def _set_custom_version(self, cfg: IniConfig, version: str): cfg.set('core', 'custom_version', version)
def _write_project_config(self): if not self._ticket_id or not self._upstream_branch or not self._branch: raise ProjectUpdateError('Missing details') cfg = IniConfig() cfg.config_file = os.path.join(self._project_dir, Project.CFG_FILE) cfg.set('core', 'version', '1') cfg.set('core', 'custom_version', INITIAL_VERSION) # branch is git branch, name is the project directory name cfg.set('core', 'name', self._name) cfg.set('main', 'branch', self._branch) cfg.set('main', 'ticket_id', self._ticket_id) cfg.set('main', 'maint_branch', self._upstream_branch) cfg.set('main', 'remote', self._upstream_remote) cfg.write()
def _core_version(self, cfg: IniConfig) -> str: return cfg.get('core', 'version')
def _custom_version(self, cfg: IniConfig) -> str: return cfg.get_or_default_value('core', 'custom_version', INITIAL_VERSION)
def _open_cfg(self) -> IniConfig: cfg = IniConfig() cfg.open(os.path.join(self._project_dir, Project.CFG_FILE)) return cfg
def __write_inverse_bool_entry(self, meta_config_entry: typing.Dict, new_config, config: IniConfig): section, option = self._get_section_option(meta_config_entry) config.set(section, option, convert_from_bool(not new_config))
def __init__(self, name: str): self.name = name self._project_dir = f'{app_config().projectdir}/{name}' self.config = IniConfig() self.config.open(f'{self._project_dir}/{self.CFG_FILE}') self.ext = _project_ext_type(self) if _project_ext_type else None
def test_set_get_save_load(self): # Test assumes it self.assert_false(os.path.exists(self.cfg_file)) cfg = IniConfig() cfg.open(self.cfg_file) for (section, option, value) in self.settings: cfg.set(section, option, value) self._verify_config(cfg) # Before the first write it can't exist self.assert_false(os.path.exists(self.cfg_file)) cfg.write() self.assert_true(os.path.exists(self.cfg_file)) with open(self.cfg_file, 'r') as f: content = f.read() # In fact, it is 67, but it cannot be guaranteed self.assert_true(len(content) > 1) # let's open it new_config = IniConfig() new_config.open(self.cfg_file) self._verify_config(new_config) os.unlink(self.cfg_file)
def test_other_functions(self): # Test assumes it self.assert_false(os.path.exists(self.cfg_file)) cfg = IniConfig() cfg.open(self.cfg_file) # testing has self.assert_false(cfg.has('an', 'apple')) cfg.set('an', 'apple', 'is red') self.assert_equal(cfg.get('an', 'apple'), 'is red') self.assert_true(cfg.has('an', 'apple')) cfg.remove('an', 'apple') self.assert_false(cfg.has('an', 'apple')) # cfg must not be empty cfg.set('an', 'apple', 'is red') self.assert_equal(cfg.get('an', 'apple'), 'is red') # testing default return values self.assert_equal(cfg.get_sections(), ['an']) self.assert_equal(cfg.get_options('an'), ['apple']) self.assert_equal(cfg.get_options('death star'), []) self.assert_equal(cfg.get('siths', 'darth vader'), None) cfg.set('an apple', 'is red', '!%@#""' + "\nangry bird") self.assert_equal(cfg.get('an apple', 'is red'), '!%@#""' + "\nangry bird") self.assert_equal(cfg.get_or_default_value('an apple', 'is red', 'green'), '!%@#""' + "\nangry bird") self.assert_equal(cfg.get_or_default_value('an apple', 'is not red', 'green'), 'green')
def test_write_without_open_fails(self): cfg = IniConfig() self.assert_raises(Exception, cfg.write)
def __load_int_item(self, meta_config_entry: typing.Dict, config: IniConfig): section, option = self._get_section_option(meta_config_entry) value = config.get_or_default_value(section, option, meta_config_entry['default']) return int(value)