Commit bac98294 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Allow configuration options to be overridden by commandline flags.

When obtaining a configuration object, it is now possible to pass
certain values to be overridden no matter what settings were made in the
configuration files.

This is used to let the -t and -d flags (location of todo.txt and
archive respectively) override anything that is mentioned in
configuration files.

This fixes a bug where the edit subcommand did not respect the -t flag,
because it was simply reading the location from the configuration file.
Now the configuration is overridden when -t is passed.

Thanks to Jacek for reporting the broken 'edit' command.
parent 9ab686d6
......@@ -29,5 +29,13 @@ class ConfigTest(TopydoTest):
def test_config3(self):
self.assertTrue(config("test/data/config2").ignore_weekends())
def test_config4(self):
""" Test that value in file is overridden by parameter. """
overrides = {
('topydo', 'default_command'): 'edit'
}
self.assertEqual(config("test/data/config1", p_overrides=overrides).default_command(), 'edit')
if __name__ == '__main__':
unittest.main()
......@@ -45,7 +45,7 @@ class CLIApplication(CLIApplicationBase):
""" Main entry function. """
args = self._process_flags()
self.todofile = TodoFile.TodoFile(self.path)
self.todofile = TodoFile.TodoFile(config().todotxt())
self.todolist = TodoList.TodoList(self.todofile.read())
(subcommand, args) = get_subcommand(args)
......
......@@ -112,11 +112,6 @@ class CLIApplicationBase(object):
"""
def __init__(self):
self.todolist = TodoList.TodoList([])
self.config = config()
self.path = self.config.todotxt()
self.archive_path = self.config.archive()
self.todofile = None
def _usage(self):
......@@ -135,24 +130,25 @@ class CLIApplicationBase(object):
error(str(e))
sys.exit(1)
alt_path = None
alt_archive = None
alt_config_path = None
overrides = {}
for opt, value in opts:
if opt == "-c":
self.config = config(value)
alt_config_path = value
elif opt == "-t":
alt_path = value
overrides[('topydo', 'filename')] = value
elif opt == "-d":
alt_archive = value
overrides[('topydo', 'archive_filename')] = value
elif opt == "-v":
version()
else:
self._usage()
self.path = alt_path if alt_path else self.config.todotxt()
self.archive_path = alt_archive \
if alt_archive else self.config.archive()
if alt_config_path:
config(alt_config_path, overrides)
elif len(overrides):
config(p_overrides=overrides)
return args
......@@ -163,7 +159,7 @@ class CLIApplicationBase(object):
This means that all completed tasks are moved to the archive file
(defaults to done.txt).
"""
archive_file = TodoFile.TodoFile(self.archive_path)
archive_file = TodoFile.TodoFile(config().archive())
archive = TodoListBase.TodoListBase(archive_file.read())
if archive:
......
......@@ -51,7 +51,7 @@ class PromptApplication(CLIApplicationBase):
""" Main entry function. """
args = self._process_flags()
self.todofile = TodoFile.TodoFile(self.path)
self.todofile = TodoFile.TodoFile(config().todotxt())
self.todolist = TodoList.TodoList(self.todofile.read())
# suppress upstream issue with Python 2.7
......
......@@ -26,12 +26,17 @@ class ConfigError(Exception):
return self.text
class _Config:
def __init__(self, p_path=None):
def __init__(self, p_path=None, p_overrides=None):
"""
Constructor.
If p_path is given, that is the only configuration file that will be
read.
If p_overrides is given, some options are ultimately overridden. This
is for some command line options which override any configuration file
(such as todo.txt location passed with -t). The key is a tuple of
(section, option), the value is the option's value.
"""
self.sections = ['topydo', 'tags', 'sort', 'ls', 'dep']
......@@ -84,6 +89,10 @@ class _Config:
self._supplement_sections()
if p_overrides:
for (section, option), value in p_overrides.items():
self.cp.set(section, option, value)
def _supplement_sections(self):
for section in self.sections:
if not self.cp.has_section(section):
......@@ -177,17 +186,21 @@ class _Config:
hidden_tags = self.cp.get('ls', 'hide_tags')
return [] if hidden_tags == '' else hidden_tags.split(',')
def config(p_path=None):
def config(p_path=None, p_overrides=None):
"""
Retrieve the config instance.
If a path is given, the instance is overwritten by the one that supplies an
additional filename (for testability). Moreover, no other configuration
files will be read when a path is given.
Overrides will discard a setting in any configuration file and use the
passed value instead. Structure: (section, option) => value
The previous configuration instance will be discarded.
"""
if not config.instance or p_path != None:
if not config.instance or p_path != None or p_overrides != None:
try:
config.instance = _Config(p_path)
config.instance = _Config(p_path, p_overrides)
except configparser.ParsingError as perr:
raise ConfigError(str(perr))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment