core.error: better defensive handling for my.core.source when parts of config are missing
This commit is contained in:
parent
094519acaf
commit
270080bd56
2 changed files with 24 additions and 5 deletions
|
@ -201,7 +201,12 @@ def error_to_json(e: Exception) -> Json:
|
||||||
MODULE_SETUP_URL = 'https://github.com/karlicoss/HPI/blob/master/doc/SETUP.org#private-configuration-myconfig'
|
MODULE_SETUP_URL = 'https://github.com/karlicoss/HPI/blob/master/doc/SETUP.org#private-configuration-myconfig'
|
||||||
|
|
||||||
|
|
||||||
def warn_my_config_import_error(err: Union[ImportError, AttributeError], help_url: Optional[str] = None) -> bool:
|
def warn_my_config_import_error(
|
||||||
|
err: Union[ImportError, AttributeError],
|
||||||
|
*,
|
||||||
|
help_url: Optional[str] = None,
|
||||||
|
module_name: Optional[str] = None,
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
If the user tried to import something from my.config but it failed,
|
If the user tried to import something from my.config but it failed,
|
||||||
possibly due to missing the config block in my.config?
|
possibly due to missing the config block in my.config?
|
||||||
|
@ -233,10 +238,24 @@ See {help_url}\
|
||||||
config_obj = cast(object, getattr(err, 'obj')) # the object that caused the attribute error
|
config_obj = cast(object, getattr(err, 'obj')) # the object that caused the attribute error
|
||||||
# e.g. active_browser for my.browser
|
# e.g. active_browser for my.browser
|
||||||
nested_block_name = err.name
|
nested_block_name = err.name
|
||||||
if config_obj.__module__ == 'my.config':
|
errmsg = f"""You're likely missing the nested config block for '{getattr(config_obj, '__name__', str(config_obj))}.{nested_block_name}'.
|
||||||
click.secho(f"""You're likely missing the nested config block for '{getattr(config_obj, '__name__', str(config_obj))}.{nested_block_name}'.
|
|
||||||
See {help_url} or check the corresponding module.py file for an example\
|
See {help_url} or check the corresponding module.py file for an example\
|
||||||
""", fg='yellow', err=True)
|
"""
|
||||||
|
if config_obj.__module__ == 'my.config':
|
||||||
|
click.secho(errmsg, fg='yellow', err=True)
|
||||||
|
return True
|
||||||
|
if module_name is not None and nested_block_name == module_name.split('.')[-1]:
|
||||||
|
# this tries to cover cases like these
|
||||||
|
# user config:
|
||||||
|
# class location:
|
||||||
|
# class via_ip:
|
||||||
|
# accuracy = 10_000
|
||||||
|
# then when we import it, we do something like
|
||||||
|
# from my.config import location
|
||||||
|
# user_config = location.via_ip
|
||||||
|
# so if location is present, but via_ip is not, we get
|
||||||
|
# AttributeError: type object 'location' has no attribute 'via_ip'
|
||||||
|
click.secho(errmsg, fg='yellow', err=True)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
click.echo(f"Unexpected error... {err}", err=True)
|
click.echo(f"Unexpected error... {err}", err=True)
|
||||||
|
|
|
@ -65,7 +65,7 @@ class core:
|
||||||
""")
|
""")
|
||||||
# try to check if this is a config error or based on dependencies not being installed
|
# try to check if this is a config error or based on dependencies not being installed
|
||||||
if isinstance(err, (ImportError, AttributeError)):
|
if isinstance(err, (ImportError, AttributeError)):
|
||||||
matched_config_err = warn_my_config_import_error(err, help_url=help_url)
|
matched_config_err = warn_my_config_import_error(err, module_name=module_name, help_url=help_url)
|
||||||
# if we determined this wasn't a config error, and it was an attribute error
|
# if we determined this wasn't a config error, and it was an attribute error
|
||||||
# it could be *any* attribute error -- we should raise this since its otherwise a fatal error
|
# it could be *any* attribute error -- we should raise this since its otherwise a fatal error
|
||||||
# from some code in the module failing
|
# from some code in the module failing
|
||||||
|
|
Loading…
Add table
Reference in a new issue