Source code for koapy.cli.extensions.parser

import sys

from argparse import Namespace
from typing import Any, Callable, List, Optional, Sequence, Tuple, TypeVar, Union

import click

from click import Command

[docs]Function = TypeVar("Function", bound=Callable[..., Any])
[docs]FunctionOrCommand = TypeVar( "FunctionOrCommand", bound=Union[Callable[..., Any], Command] )
[docs]ArgumentDecorator = Callable[[FunctionOrCommand], FunctionOrCommand]
[docs]CommandDecorator = Callable[[Function], Command]
[docs]class ArgumentParser:
[docs] def parse_args( self, args: Optional[Sequence[str]] = None, namespace: Optional[Namespace] = None, ) -> Namespace: raise NotImplementedError
[docs] def parse_known_args( self, args: Optional[Sequence[str]] = None, namespace: Optional[Namespace] = None, ) -> Tuple[Namespace, List[str]]: raise NotImplementedError
[docs]class ClickArgumentParser(ArgumentParser): _unrecognized_args_attr = "args" def __init__( self, params: Sequence[ArgumentDecorator], command: Optional[CommandDecorator] = None, help_option_names: Optional[Sequence[str]] = None, ): if help_option_names is None: help_option_names = ["-h", "--help"] if command is None: command = click.command( context_settings=dict(help_option_names=help_option_names) ) self._params = params self._command = command self._help_option_names = help_option_names def _callback(self, *args, **kwargs): return args, kwargs def _parse_args( self, args: Optional[Sequence[str]] = None, namespace: Optional[Namespace] = None, ignore_unknown_options: bool = False, allow_extra_args: bool = False, allow_interspersed_args: bool = True, ) -> Tuple[Namespace, List[str]]: if args is None: args = sys.argv[1:] else: args = list(args) if namespace is None: namespace = Namespace() def callback(*args, **kwargs): return self._callback(*args, **kwargs) if ignore_unknown_options: unrecognized_args_param = click.argument( self._unrecognized_args_attr, nargs=-1, type=click.UNPROCESSED, metavar="[ARGS]...", ) callback = unrecognized_args_param(callback) for decorator in reversed(self._params): callback = decorator(callback) command = self._command(callback) context_settings = dict( help_option_names=self._help_option_names, ignore_unknown_options=ignore_unknown_options, allow_extra_args=allow_extra_args, allow_interspersed_args=allow_interspersed_args, ) command.context_settings.update(context_settings) ret = command.main(args, standalone_mode=False) if isinstance(ret, int): sys.exit(ret) callback_args, callback_kwargs = ret assert len(callback_args) == 0 for key, value in callback_kwargs.items(): setattr(namespace, key, value) unrecognized_args = [] if hasattr(namespace, self._unrecognized_args_attr): unrecognized_args = getattr(namespace, self._unrecognized_args_attr) unrecognized_args = list(unrecognized_args) delattr(namespace, self._unrecognized_args_attr) return namespace, unrecognized_args
[docs] def parse_args( self, args: Optional[Sequence[str]] = None, namespace: Optional[Namespace] = None, ) -> Namespace: namespace, _unrecognized_args = self._parse_args(args, namespace) return namespace
[docs] def parse_known_args( self, args: Optional[Sequence[str]] = None, namespace: Optional[Namespace] = None, ) -> Tuple[Namespace, List[str]]: namespace, unrecognized_args = self._parse_args( args, namespace, ignore_unknown_options=True, ) return namespace, unrecognized_args