From 17dcb4275246a3826766d2b102b26ad6b3e931a6 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Wed, 30 Nov 2016 16:07:17 -0500 Subject: [PATCH] klippy: Validate that options in the config file exist Check that all options specified in the config file are valid. This catches possible typos and spelling errors in variable names that have a default. Signed-off-by: Kevin O'Connor --- docs/Todo.md | 16 ++++------------ klippy/klippy.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/docs/Todo.md b/docs/Todo.md index 74c6790a..b634c173 100644 --- a/docs/Todo.md +++ b/docs/Todo.md @@ -4,18 +4,10 @@ features still to be implemented. In no particular order: Host user interaction ===================== -* Improve error reporting: - - * Improve error checks on config file values. If a parameter is - incorrect or missing a more friendly error message should be - presented to the user. - - * Warn on any unused config settings (to catch spelling errors or - fields defined in an incorrect section). - - * Find a better way to report errors. Octoprint sometimes doesn't - highlight an error (one has to look in the terminal tab to find the - error) and errors written to the log can be non-obvious to a user. +* See if there is a better way to report errors. Octoprint sometimes + doesn't highlight an error (one has to look in the terminal tab to + find the error) and errors written to the log can be non-obvious to + a user. * Improve startup: diff --git a/klippy/klippy.py b/klippy/klippy.py index f4cdbb41..9b7a68ab 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -44,6 +44,8 @@ class ConfigWrapper: if (default is not self.sentinel and not self.printer.fileconfig.has_option(self.section, option)): return default + self.printer.all_config_options[ + (self.section.lower(), option.lower())] = 1 try: return parser(self.section, option) except self.error, e: @@ -79,6 +81,7 @@ class Printer: self.stats_timer = self.reactor.register_timer(self.stats) self.connect_timer = self.reactor.register_timer( self.connect, self.reactor.NOW) + self.all_config_options = {} self.state_message = message_startup self.debugoutput = self.dictionary = None self.fileconfig = None @@ -118,6 +121,19 @@ class Printer: self.objects[oname].build_config() self.gcode.build_config() self.mcu.build_config() + def validate_config(self): + valid_sections = dict([(s, 1) for s, o in self.all_config_options]) + for section in self.fileconfig.sections(): + section = section.lower() + if section not in valid_sections: + raise ConfigParser.Error("Unknown config file section '%s'" % ( + section,)) + for option in self.fileconfig.options(section): + option = option.lower() + if (section, option) not in self.all_config_options: + raise ConfigParser.Error( + "Unknown option '%s' in section '%s'" % ( + option, section)) def connect(self, eventtime): try: self.load_config() @@ -127,6 +143,7 @@ class Printer: self.mcu.connect_file(self.debugoutput, self.dictionary) self.mcu.connect() self.build_config() + self.validate_config() self.gcode.set_printer_ready(True) self.state_message = "Running" except ConfigParser.Error, e: