generated from jCloud/repository-template
feat(cli): add error handling
The CLI now handles error that may result from user input and prints an error message. Following error types are handled: - file not found - not a directory - directory instead of file - file exists - permission error - general operating system errors - Unicode errors - errors parsing project source code Additionally, KeyboardInterrupt and BrokenPipeError are catched and an appropriate exit code is returned.
This commit is contained in:
1 file changed
+48
-10
@@ -22,9 +22,11 @@ __all__ = [
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import sys
|
||||
from .parsers.python import VALID_SECTIONS as VALID_PYTHON_SECTIONS
|
||||
|
||||
_LANG_PYTHON = 'python'
|
||||
_PROGRAM_NAME = 'jcloud-docsgen'
|
||||
|
||||
def existing_directory(path: str) -> pathlib.Path:
|
||||
_path = path
|
||||
@@ -35,6 +37,19 @@ def existing_directory(path: str) -> pathlib.Path:
|
||||
raise argparse.ArgumentTypeError(f'{_path}: not a directory')
|
||||
return path
|
||||
|
||||
def error(message: str, exit_code: int = 1):
|
||||
'''
|
||||
Shows an error message and returns the exit code.
|
||||
|
||||
:param message: The error message to show.
|
||||
:type message: str
|
||||
:param exit_code: The exit code.
|
||||
:type exit_code: int
|
||||
'''
|
||||
|
||||
print(f'{_PROGRAM_NAME}: error: {message}', file = sys.stderr)
|
||||
return exit_code
|
||||
|
||||
def main(argv = None) -> int:
|
||||
common_parser = argparse.ArgumentParser(add_help = False)
|
||||
common_parser.add_argument(
|
||||
@@ -93,15 +108,38 @@ def main(argv = None) -> int:
|
||||
if args.output_dir is None:
|
||||
args.output_dir = args.project_directory / 'docs/reference'
|
||||
|
||||
if args.language == _LANG_PYTHON:
|
||||
from .parsers.python import generate
|
||||
generate(
|
||||
args.project_directory,
|
||||
args.output_dir,
|
||||
include_sections = args.sections,
|
||||
exclude_sections = args.sections_exclude,
|
||||
allow_html = args.allow_html,
|
||||
allow_tables = args.allow_tables
|
||||
)
|
||||
try:
|
||||
if args.language == _LANG_PYTHON:
|
||||
from .parsers.python import generate
|
||||
generate(
|
||||
args.project_directory,
|
||||
args.output_dir,
|
||||
include_sections = args.sections,
|
||||
exclude_sections = args.sections_exclude,
|
||||
allow_html = args.allow_html,
|
||||
allow_tables = args.allow_tables
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
return error(f'{exc.filename}: no such file or directory')
|
||||
except NotADirectoryError as exc:
|
||||
return error(f'{exc.filename}: not a directory')
|
||||
except IsADirectoryError as exc:
|
||||
return error(f'{exc.filename}: is a directory')
|
||||
except FileExistsError as exc:
|
||||
return error(f'{exc.filename}: file already exists')
|
||||
except PermissionError as exc:
|
||||
return error(f'{exc.filename}: permission denied')
|
||||
except OSError as exc:
|
||||
return error(f'{exc.filename}: {exc.args[1]}')
|
||||
except UnicodeError:
|
||||
return error('invalid text encoding')
|
||||
except SyntaxError:
|
||||
# TODO: add a custom exception class to clearify that a project
|
||||
# parsing syntax error is meant.
|
||||
return error(f'syntax error in project source code')
|
||||
except KeyboardInterrupt:
|
||||
return 130
|
||||
except BrokenPipeError:
|
||||
return 141
|
||||
|
||||
return 0
|
||||
Reference in new issue
Block a user