Files
jcloud-docsgen/src/jcloud_docsgen/cli/cli.py
T
jakob.scheid caa8e04047 style: limit line length to 79 characters
Limited the lengths of all lines to 79 characters (if possible).
Additionally, some other lines were breaked for consistence.
2026-09-18 16:57:45 +02:00

176 lines
5.1 KiB
Python

# Copyright 2026 jCloud
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''
The command line interface
'''
import argparse
import pathlib
import sys
from .languages.python import VALID_SECTIONS as VALID_PYTHON_SECTIONS
__all__ = [
'existing_directory',
'error',
'create_argument_parser',
'main'
]
_LANG_PYTHON = 'python'
_PROGRAM_NAME = 'jcloud-docsgen'
def existing_directory(path: str) -> pathlib.Path:
_path = path
path = pathlib.Path(_path)
if not path.exists():
raise argparse.ArgumentTypeError(
f'{_path}: no such file or directory'
)
if not path.is_dir():
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 create_argument_parser() -> argparse.ArgumentParser:
'''
Prepares a parser to parse the command-line arguments using
argparse.
:return: The parser.
:rtype: argparse.ArgumentParser
'''
common_parser = argparse.ArgumentParser(add_help = False)
common_parser.add_argument(
'project_directory',
type = existing_directory,
nargs = '?',
default = pathlib.Path('.'),
help = 'The directory of the project'
)
common_parser.add_argument(
'-o',
'--output-dir',
type = pathlib.Path,
help = 'the output directory the documentation will be written to'
)
argument_parser = argparse.ArgumentParser()
subparsers = argument_parser.add_subparsers(
dest = 'language',
required = True
)
python_parser = subparsers.add_parser(
_LANG_PYTHON,
parents = [common_parser],
help = 'generate documentation for Python project'
)
python_parser.add_argument(
'-s',
'--sections',
nargs = '+',
choices = VALID_PYTHON_SECTIONS,
help = 'the sections to be included in the documentation'
)
python_parser.add_argument(
'-S',
'--sections-exclude',
nargs = '+',
default = [],
choices = VALID_PYTHON_SECTIONS,
help = (
'the sections to be excluded in the documentation. '
'If a section shall be included AND excluded, it is excluded.'
)
)
python_parser.add_argument(
'-H',
'--allow-html',
action = 'store_true',
help = (
'indicates whether HTML is allowed in the documentation. '
'By default, HTML is disabled.'
)
)
python_parser.add_argument(
'-T',
'--allow-tables',
action = 'store_true',
help = (
'indicates whether Markdown tables are allowed in the '
'documentation. By default, Markdown tables are disabled. '
'Warning: Markdown tables are not CommonMark.'
)
)
return argument_parser
def main(argv = None) -> int:
argument_parser = create_argument_parser()
args = argument_parser.parse_args(argv)
if args.output_dir is None:
args.output_dir = args.project_directory / 'docs/reference'
try:
if args.language == _LANG_PYTHON:
from .languages.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