summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2013-10-30 11:43:12 +0000
committerLars Wirzenius <liw@liw.fi>2013-10-30 11:43:12 +0000
commitc8c2b9c9ab7a207b9a202bbfda901d9cb20e863c (patch)
tree0a2a242c57f2f6ce971640080b42b53b94196a05
parent7efa8ac96f1debcfe35b4203f7b9d442dea02587 (diff)
parent9a2f797374c4c2733e4a25a1cdbd455a8a6ae33a (diff)
downloadcliapp-c8c2b9c9ab7a207b9a202bbfda901d9cb20e863c.tar.gz
Merge branch 'liw/unknown-var-in-config-message'
-rw-r--r--NEWS4
-rw-r--r--cliapp/__init__.py4
-rw-r--r--cliapp/app.py3
-rw-r--r--cliapp/settings.py24
-rw-r--r--cliapp/settings_tests.py13
5 files changed, 40 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index 93de554..9b2891e 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ Version 1.UNRELEASED
* `cliapp` now logs the current working directory, uid, effective uid,
gid, and effective gid at startup.
+* `cliapp` (`Settings.load_configs`) now reports an unknown
+ variable in a configuration file with a nice error message, rather
+ than a stack trace.
+
Version 1.20130808
------------------
diff --git a/cliapp/__init__.py b/cliapp/__init__.py
index 6e4d408..3536626 100644
--- a/cliapp/__init__.py
+++ b/cliapp/__init__.py
@@ -19,10 +19,10 @@ __version__ = '1.20130808'
from fmt import TextFormat
+from app import Application, AppException
from settings import (Settings, log_group_name, config_group_name,
- perf_group_name)
+ perf_group_name, UnknownConfigVariable)
from runcmd import runcmd, runcmd_unchecked, shell_quote, ssh_runcmd
-from app import Application, AppException
# The plugin system
from hook import Hook, FilterHook
diff --git a/cliapp/app.py b/cliapp/app.py
index 54a6839..5e49bf0 100644
--- a/cliapp/app.py
+++ b/cliapp/app.py
@@ -190,6 +190,9 @@ class Application(object):
self.process_args(args)
self.cleanup()
self.disable_plugins()
+ except cliapp.UnknownConfigVariable, e: # pragma: no cover
+ stderr.write('ERROR: %s\n' % str(e))
+ sys.exit(1)
except AppException, e:
log(traceback.format_exc())
stderr.write('ERROR: %s\n' % str(e))
diff --git a/cliapp/settings.py b/cliapp/settings.py
index b58a3e7..4b65060 100644
--- a/cliapp/settings.py
+++ b/cliapp/settings.py
@@ -36,6 +36,16 @@ default_group_names = [
]
+class UnknownConfigVariable(cliapp.AppException):
+
+ def __init__(self, filename, name):
+ self.msg = (
+ '%s: Unknown configuration variable %s' % (filename, name))
+
+ def __str__(self): # pragma: no cover
+ return self.msg
+
+
class Setting(object):
action = 'store'
@@ -699,8 +709,10 @@ class Settings(object):
config_files = property(_get_config_files, _set_config_files)
- def set_from_raw_string(self, name, raw_string):
+ def set_from_raw_string(self, pathname, name, raw_string):
'''Set value of a setting from a raw, unparsed string value.'''
+ if name not in self._settingses:
+ raise UnknownConfigVariable(pathname, name)
s = self._settingses[name]
s.parse_value(raw_string)
return s
@@ -724,11 +736,11 @@ class Settings(object):
cp.readfp(f)
f.close()
- for name in cp.options('config'):
- value = cp.get('config', name)
- s = self.set_from_raw_string(name, value)
- if hasattr(s, 'using_default_value'):
- s.using_default_value = True
+ for name in cp.options('config'):
+ value = cp.get('config', name)
+ s = self.set_from_raw_string(pathname, name, value)
+ if hasattr(s, 'using_default_value'):
+ s.using_default_value = True
# Remember the ConfigParser for use in as_cp later on.
self._cp = cp
diff --git a/cliapp/settings_tests.py b/cliapp/settings_tests.py
index 7a44d81..b617d50 100644
--- a/cliapp/settings_tests.py
+++ b/cliapp/settings_tests.py
@@ -336,6 +336,19 @@ bar = ping, pong
self.assertEqual(self.settings['foo'], 'red')
self.assertEqual(self.settings['bar'], ['blue', 'white'])
+ def test_load_configs_raises_error_for_unknown_variable(self):
+
+ def mock_open(filename, mode=None):
+ return StringIO.StringIO('''\
+[config]
+unknown = variable
+''')
+
+ self.assertRaises(
+ cliapp.UnknownConfigVariable,
+ self.settings.load_configs,
+ open=mock_open)
+
def test_load_configs_ignore_errors_opening_a_file(self):
def mock_open(filename, mode=None):