Less scary message on config.yaml parsing error
This commit is contained in:
parent
55ed4211f9
commit
0fd510a51f
5 changed files with 81 additions and 23 deletions
|
|
@ -52,6 +52,11 @@ if version_info.major == 2 and version_info.minor <= 7 and version_info.micro <
|
|||
|
||||
del version_info
|
||||
|
||||
#~~ custom exceptions
|
||||
|
||||
class FatalStartupError(BaseException):
|
||||
pass
|
||||
|
||||
#~~ init methods to bring up platform
|
||||
|
||||
def init_platform(basedir, configfile, use_logging_file=True, logging_file=None,
|
||||
|
|
@ -79,8 +84,14 @@ def init_platform(basedir, configfile, use_logging_file=True, logging_file=None,
|
|||
def init_settings(basedir, configfile):
|
||||
"""Inits the settings instance based on basedir and configfile to use."""
|
||||
|
||||
from octoprint.settings import settings
|
||||
return settings(init=True, basedir=basedir, configfile=configfile)
|
||||
from octoprint.settings import settings, InvalidSettings
|
||||
try:
|
||||
return settings(init=True, basedir=basedir, configfile=configfile)
|
||||
except InvalidSettings as e:
|
||||
message = "Error parsing the configuration file, it appears to be invalid YAML."
|
||||
if e.line is not None and e.column is not None:
|
||||
message += " The parser reported an error on line {}, column {}.".format(e.line, e.column)
|
||||
raise FatalStartupError(message)
|
||||
|
||||
|
||||
def init_logging(settings, use_logging_file=True, logging_file=None, default_config=None, debug=False, verbosity=0, uncaught_logger=None, uncaught_handler=None):
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import json
|
|||
import octoprint_client
|
||||
|
||||
from octoprint.cli import pass_octoprint_ctx, bulk_options, standard_options
|
||||
from octoprint import init_settings
|
||||
from octoprint import init_settings, FatalStartupError
|
||||
|
||||
|
||||
class JsonStringParamType(click.ParamType):
|
||||
|
|
@ -36,10 +36,16 @@ def client_commands():
|
|||
@click.option("--https", is_flag=True)
|
||||
@click.option("--prefix", type=click.STRING)
|
||||
@pass_octoprint_ctx
|
||||
def client(obj, host, port, httpuser, httppass, https, prefix):
|
||||
@click.pass_context
|
||||
def client(ctx, obj, host, port, httpuser, httppass, https, prefix):
|
||||
"""Basic API client."""
|
||||
obj.settings = init_settings(obj.basedir, obj.configfile)
|
||||
octoprint_client.init_client(obj.settings, https=https, httpuser=httpuser, httppass=httppass, host=host, port=port, prefix=prefix)
|
||||
try:
|
||||
obj.settings = init_settings(obj.basedir, obj.configfile)
|
||||
octoprint_client.init_client(obj.settings, https=https, httpuser=httpuser, httppass=httppass, host=host, port=port, prefix=prefix)
|
||||
except FatalStartupError as e:
|
||||
click.echo(e.message, err=True)
|
||||
click.echo("There was a fatal error initializing the client.", err=True)
|
||||
ctx.exit(-1)
|
||||
|
||||
|
||||
def log_response(response, status_code=True, body=True, headers=False):
|
||||
|
|
|
|||
|
|
@ -48,9 +48,14 @@ class OctoPrintPluginCommands(click.MultiCommand):
|
|||
|
||||
# initialize settings and plugin manager based on provided
|
||||
# context (basedir and configfile)
|
||||
from octoprint import init_settings, init_pluginsystem
|
||||
self.settings = init_settings(ctx.obj.basedir, ctx.obj.configfile)
|
||||
self.plugin_manager = init_pluginsystem(self.settings)
|
||||
from octoprint import init_settings, init_pluginsystem, FatalStartupError
|
||||
try:
|
||||
self.settings = init_settings(ctx.obj.basedir, ctx.obj.configfile)
|
||||
self.plugin_manager = init_pluginsystem(self.settings)
|
||||
except FatalStartupError as e:
|
||||
click.echo(e.message, err=True)
|
||||
click.echo("There was a fatal error initializing the settings or the plugin system.", err=True)
|
||||
ctx.exit(-1)
|
||||
|
||||
# fetch registered hooks
|
||||
self.hooks = self.plugin_manager.get_hooks("octoprint.cli.commands")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from octoprint.cli import pass_octoprint_ctx, bulk_options, standard_options
|
|||
def run_server(basedir, configfile, host, port, debug, allow_root, logging_config, verbosity, octoprint_daemon = None):
|
||||
"""Initializes the environment and starts up the server."""
|
||||
|
||||
from octoprint import init_platform, __display_version__
|
||||
from octoprint import init_platform, __display_version__, FatalStartupError
|
||||
|
||||
def log_startup(_):
|
||||
logging.getLogger("octoprint.server").info("Starting OctoPrint {}".format(__display_version__))
|
||||
|
|
@ -29,17 +29,27 @@ def run_server(basedir, configfile, host, port, debug, allow_root, logging_confi
|
|||
"install PyOpenSSL plus its dependencies. For details see "
|
||||
"https://urllib3.readthedocs.org/en/latest/security.html#openssl-pyopenssl")
|
||||
|
||||
settings, _, plugin_manager = init_platform(basedir,
|
||||
configfile,
|
||||
logging_file=logging_config,
|
||||
debug=debug,
|
||||
verbosity=verbosity,
|
||||
uncaught_logger=__name__,
|
||||
after_logging=log_startup)
|
||||
|
||||
from octoprint.server import Server
|
||||
octoprint_server = Server(settings=settings, plugin_manager=plugin_manager, host=host, port=port, debug=debug, allow_root=allow_root, octoprint_daemon=octoprint_daemon)
|
||||
octoprint_server.run()
|
||||
try:
|
||||
settings, _, plugin_manager = init_platform(basedir,
|
||||
configfile,
|
||||
logging_file=logging_config,
|
||||
debug=debug,
|
||||
verbosity=verbosity,
|
||||
uncaught_logger=__name__,
|
||||
after_logging=log_startup)
|
||||
except FatalStartupError as e:
|
||||
click.echo(e.message, err=True)
|
||||
click.echo("There was a fatal error starting up OctoPrint.", err=True)
|
||||
else:
|
||||
from octoprint.server import Server
|
||||
octoprint_server = Server(settings=settings,
|
||||
plugin_manager=plugin_manager,
|
||||
host=host,
|
||||
port=port,
|
||||
debug=debug,
|
||||
allow_root=allow_root,
|
||||
octoprint_daemon=octoprint_daemon)
|
||||
octoprint_server.run()
|
||||
|
||||
#~~ server options
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ __copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms
|
|||
import sys
|
||||
import os
|
||||
import yaml
|
||||
import yaml.parser
|
||||
import logging
|
||||
import re
|
||||
import uuid
|
||||
|
|
@ -345,6 +346,14 @@ class NoSuchSettingsPath(BaseException):
|
|||
pass
|
||||
|
||||
|
||||
class InvalidSettings(BaseException):
|
||||
def __init__(self, message, line=None, column=None, details=None):
|
||||
self.message = message
|
||||
self.line = line
|
||||
self.column = column
|
||||
self.details = details
|
||||
|
||||
|
||||
class HierarchicalChainMap(ChainMap):
|
||||
|
||||
def deep_dict(self, root=None):
|
||||
|
|
@ -747,8 +756,25 @@ class Settings(object):
|
|||
def load(self, migrate=False):
|
||||
if os.path.exists(self._configfile) and os.path.isfile(self._configfile):
|
||||
with open(self._configfile, "r") as f:
|
||||
self._config = yaml.safe_load(f)
|
||||
self._mtime = self.last_modified
|
||||
try:
|
||||
self._config = yaml.safe_load(f)
|
||||
self._mtime = self.last_modified
|
||||
except yaml.YAMLError as e:
|
||||
details = e.message
|
||||
|
||||
if hasattr(e, "problem_mark"):
|
||||
line = e.problem_mark.line
|
||||
column = e.problem_mark.column
|
||||
else:
|
||||
line = None
|
||||
column = None
|
||||
|
||||
raise InvalidSettings("Invalid YAML file: {}".format(self._configfile),
|
||||
details=details,
|
||||
line=line,
|
||||
column=column)
|
||||
except:
|
||||
raise
|
||||
# changed from else to handle cases where the file exists, but is empty / 0 bytes
|
||||
if not self._config:
|
||||
self._config = dict()
|
||||
|
|
|
|||
Loading…
Reference in a new issue