Source code for almanac.arguments.argument_base

from abc import ABC, abstractmethod, abstractproperty
from inspect import Parameter
from typing import Any, Iterable, Optional, Union

from prompt_toolkit.completion import Completer

from ..constants import CommandLineDefaults

[docs]class ArgumentBase(ABC): """An abstract class for encapsulating a command argument. This abstract base class is extended into two variants: * :class:`~almanac.arguments.frozen_argument.FrozenArgument` * :class:`~almanac.arguments.mutable_argument.MutableArgument` It is unlikely that you should need to manually instantiate instances of these classes, as they are mainly used internally for the argument-generating decorators accessible via :class:`~almanac.core.application.Application`. """ def __init__( self, param: Parameter, *, name: Optional[str] = None, description: Optional[str] = None, completers: Optional[Union[Completer, Iterable[Completer]]] = None, hidden: bool = False ) -> None: self._param = param self._real_name = self._display_name = name if name is not None else self._real_name self._description = ( description if description is not None else CommandLineDefaults.DOC ) if completers is None: self._completers = [] elif isinstance(completers, Completer): self._completers = [completers] else: # Assume we have iterable of completers. self._completers = [x for x in completers] self._hidden = hidden @property def display_name( self ) -> str: """The name used to specify this argument from the interactive shell.""" return self._display_name @display_name.setter def display_name( self, new_display_name: str ) -> None: self._abstract_display_name_setter(new_display_name) @abstractmethod def _abstract_display_name_setter( self, new_display_name: str ) -> None: """Abstract display name setter to allow for access control.""" @abstractproperty def completers( self ) -> Iterable[Completer]: """The registered completers for this argument.""" @property def description( self ) -> str: """A description of what this argument does.""" return self._description @description.setter def description( self, new_description: str ) -> None: self._abstract_description_setter(new_description) @abstractmethod def _abstract_description_setter( self, new_description: str ) -> None: """Abstract description setter to allow for access control.""" @property def hidden( self ) -> bool: """Whether this argument should be hidden in the interactive prompt.""" return self._hidden @hidden.setter def hidden( self, new_value: bool ) -> None: self._abstract_hidden_setter(new_value) @abstractmethod def _abstract_hidden_setter( self, new_value: bool ) -> None: """Abstract hidden setter to allow for access control.""" @property def real_name( self ) -> str: """The name of this argument within the actual command coroutine.""" return self._real_name @property def param( self ) -> Parameter: """The internal :class:`inspect.Parameter` wrapped by this class.""" return self._param @property def annotation( self ) -> Any: """The annotated type of this parameter.""" return self._param.annotation @property def is_pos_only( self ) -> bool: """Whether this argument is a positional-only argument.""" return self._param.kind == self._param.POSITIONAL_ONLY @property def is_kw_only( self ) -> bool: """Whether this argument is a keyword-only argument.""" return self._param.kind == self._param.KEYWORD_ONLY @property def is_var_kw( self ) -> bool: """Whether this argument is a \*\*kwargs variant.""" # noqa return self._param.kind == self._param.VAR_KEYWORD @property def is_var_pos( self ) -> bool: """Whether this argument is an \*args variant.""" # noqa return self._param.kind == self._param.VAR_POSITIONAL @property def has_default_value( self ) -> bool: """Whether this argument has a default value.""" return self._param.default is not self._param.empty @property def default_value( self ) -> Any: """The default value of this argument (if it has one).""" return self._param.default def __str__( self ) -> str: s = self._display_name if self._real_name != self._display_name: s += f' (bound to {self._real_name})' return s def __repr__( self ) -> str: return f'<{self.__class__.__qualname__} [{str(self)}]>'