diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py index 58bc0176..fd103685 100644 --- a/cmd2/argparse_custom.py +++ b/cmd2/argparse_custom.py @@ -282,6 +282,7 @@ class CompletionItem(str): # noqa: SLOT000 """ def __new__(cls, value: object, *_args: Any, **_kwargs: Any) -> 'CompletionItem': + """Responsible for creating and returning a new instance, called before __init__ when an object is instantiated.""" return super().__new__(cls, value) def __init__(self, value: object, description: str = '', *args: Any) -> None: @@ -313,14 +314,16 @@ def orig_value(self) -> Any: class ChoicesProviderFuncBase(Protocol): """Function that returns a list of choices in support of tab completion.""" - def __call__(self) -> list[str]: ... # pragma: no cover + def __call__(self) -> list[str]: # pragma: no cover + """Enable instances to be called like functions.""" @runtime_checkable class ChoicesProviderFuncWithTokens(Protocol): """Function that returns a list of choices in support of tab completion and accepts a dictionary of prior arguments.""" - def __call__(self, *, arg_tokens: dict[str, list[str]] = {}) -> list[str]: ... # pragma: no cover # noqa: B006 + def __call__(self, *, arg_tokens: dict[str, list[str]] = {}) -> list[str]: # pragma: no cover # noqa: B006 + """Enable instances to be called like functions.""" ChoicesProviderFunc = Union[ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens] @@ -336,7 +339,8 @@ def __call__( line: str, begidx: int, endidx: int, - ) -> list[str]: ... # pragma: no cover + ) -> list[str]: # pragma: no cover + """Enable instances to be called like functions.""" @runtime_checkable @@ -351,7 +355,8 @@ def __call__( endidx: int, *, arg_tokens: dict[str, list[str]] = {}, # noqa: B006 - ) -> list[str]: ... # pragma: no cover + ) -> list[str]: # pragma: no cover + """Enable instances to be called like functions.""" CompleterFunc = Union[CompleterFuncBase, CompleterFuncWithTokens] @@ -391,6 +396,7 @@ def __init__( @property def completer(self) -> CompleterFunc: + """Retreive the internal Completer function, first type checking to ensure it is the right type.""" if not isinstance(self.to_call, (CompleterFuncBase, CompleterFuncWithTokens)): # pragma: no cover # this should've been caught in the constructor, just a backup check raise TypeError('Function is not a CompleterFunc') @@ -398,6 +404,7 @@ def completer(self) -> CompleterFunc: @property def choices_provider(self) -> ChoicesProviderFunc: + """Retreive the internal ChoicesProvider function, first type checking to ensure it is the right type.""" if not isinstance(self.to_call, (ChoicesProviderFuncBase, ChoicesProviderFuncWithTokens)): # pragma: no cover # this should've been caught in the constructor, just a backup check raise TypeError('Function is not a ChoicesProviderFunc') @@ -1350,6 +1357,7 @@ class Cmd2AttributeWrapper: """ def __init__(self, attribute: Any) -> None: + """Initialize Cmd2AttributeWrapper instances.""" self.__attribute = attribute def get(self) -> Any: diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index f4f00d68..a1845d68 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -1341,7 +1341,8 @@ def ppaged(self, msg: Any, *, end: str = '\n', chop: bool = False) -> None: # ----- Methods related to tab completion ----- def _reset_completion_defaults(self) -> None: - """Resets tab completion settings + """Reset tab completion settings. + Needs to be called each time readline runs tab completion. """ self.allow_appended_space = True @@ -2406,47 +2407,43 @@ def _raise_keyboard_interrupt(self) -> None: raise KeyboardInterrupt("Got a keyboard interrupt") def precmd(self, statement: Union[Statement, str]) -> Statement: - """Hook method executed just before the command is executed by - [cmd2.Cmd.onecmd][] and after adding it to history. + """Ran just before the command is executed by [cmd2.Cmd.onecmd][] and after adding it to history (cmd Hook method). :param statement: subclass of str which also contains the parsed input :return: a potentially modified version of the input Statement object - See [cmd2.Cmd.register_postparsing_hook][] and - [cmd2.Cmd.register_precmd_hook][] for more robust ways - to run hooks before the command is executed. See - [Hooks](../features/hooks.md) for more information. + See [cmd2.Cmd.register_postparsing_hook][] and [cmd2.Cmd.register_precmd_hook][] for more robust ways + to run hooks before the command is executed. See [Hooks](../features/hooks.md) for more information. """ return Statement(statement) if not isinstance(statement, Statement) else statement def postcmd(self, stop: bool, statement: Union[Statement, str]) -> bool: # noqa: ARG002 - """Hook method executed just after a command is executed by - [cmd2.Cmd.onecmd][]. + """Ran just after a command is executed by [cmd2.Cmd.onecmd][] (cmd inherited Hook method). :param stop: return `True` to request the command loop terminate :param statement: subclass of str which also contains the parsed input See [cmd2.Cmd.register_postcmd_hook][] and [cmd2.Cmd.register_cmdfinalization_hook][] for more robust ways - to run hooks after the command is executed. See - [Hooks](../features/hooks.md) for more information. + to run hooks after the command is executed. See [Hooks](../features/hooks.md) for more information. """ return stop def preloop(self) -> None: - """Hook method executed once when the [cmd2.Cmd.cmdloop][] - method is called. + """Ran once when the [cmd2.Cmd.cmdloop][] method is called (cmd inherited Hook method). + + This method is a stub that does nothing and exists to be overridden by subclasses. - See [cmd2.Cmd.register_preloop_hook][] for a more robust way - to run hooks before the command loop begins. See - [Hooks](../features/hooks.md) for more information. + See [cmd2.Cmd.register_preloop_hook][] for a more robust wayto run hooks before the command loop begins. + See [Hooks](../features/hooks.md) for more information. """ def postloop(self) -> None: - """Hook method executed once when the [cmd2.Cmd.cmdloop][] method is about to return. + """Ran once when the [cmd2.Cmd.cmdloop][] method is about to return (cmd inherited Hook Method). + + This method is a stub that does nothing and exists to be overridden by subclasses. - See [cmd2.Cmd.register_postloop_hook][] for a more robust way - to run hooks after the command loop completes. See - [Hooks](../features/hooks.md) for more information. + See [cmd2.Cmd.register_postloop_hook][] for a more robust way to run hooks after the command loop completes. + See [Hooks](../features/hooks.md) for more information. """ def parseline(self, line: str) -> tuple[str, str, str]: diff --git a/cmd2/command_definition.py b/cmd2/command_definition.py index 97f740b4..860fd5d1 100644 --- a/cmd2/command_definition.py +++ b/cmd2/command_definition.py @@ -86,9 +86,11 @@ class CommandSet: """ def __init__(self) -> None: - # Private reference to the CLI instance in which this CommandSet running. - # This will be set when the CommandSet is registered and it should be - # accessed by child classes using the self._cmd property. + """Private reference to the CLI instance in which this CommandSet running. + + This will be set when the CommandSet is registered and it should be + accessed by child classes using the self._cmd property. + """ self.__cmd_internal: Optional[cmd2.Cmd] = None self._settables: dict[str, Settable] = {} @@ -147,10 +149,12 @@ def on_unregistered(self) -> None: @property def settable_prefix(self) -> str: + """Read-only accessor for the underlying private settable_prefix field.""" return self._settable_prefix @property def settables(self) -> Mapping[str, Settable]: + """Read-only accessor for the underlying private settables field.""" return self._settables def add_settable(self, settable: Settable) -> None: diff --git a/cmd2/decorators.py b/cmd2/decorators.py index 3ab1c33b..61742ad3 100644 --- a/cmd2/decorators.py +++ b/cmd2/decorators.py @@ -32,7 +32,7 @@ def with_category(category: str) -> Callable[[CommandFunc], CommandFunc]: - """A decorator to apply a category to a ``do_*`` command method. + """Decorate a ``do_*`` command method to apply a category. :param category: the name of the category in which this command should be grouped when displaying the list of commands. @@ -138,7 +138,7 @@ def with_argument_list( RawCommandFuncOptionalBoolReturn[CommandParent], Callable[[ArgListCommandFunc[CommandParent]], RawCommandFuncOptionalBoolReturn[CommandParent]], ]: - """A decorator to alter the arguments passed to a ``do_*`` method. + """Decorate a ``do_*`` method to alter the arguments passed to it so it is passed a list[str]. Default passes a string of whatever the user typed. With this decorator, the decorated method will receive a list of arguments parsed from user input. @@ -160,7 +160,8 @@ def do_echo(self, arglist): import functools def arg_decorator(func: ArgListCommandFunc[CommandParent]) -> RawCommandFuncOptionalBoolReturn[CommandParent]: - """Decorator function that ingests an Argument List function and returns a raw command function. + """Decorate function that ingests an Argument List function and returns a raw command function. + The returned function will process the raw input into an argument list to be passed to the wrapped function. :param func: The defined argument list command function @@ -278,8 +279,7 @@ def with_argparser( preserve_quotes: bool = False, with_unknown_args: bool = False, ) -> Callable[[ArgparseCommandFunc[CommandParent]], RawCommandFuncOptionalBoolReturn[CommandParent]]: - """A decorator to alter a cmd2 method to populate its ``args`` argument by parsing arguments - with the given instance of argparse.ArgumentParser. + """Decorate a ``do_*`` method to populate its ``args`` argument with the given instance of argparse.ArgumentParser. :param parser: unique instance of ArgumentParser or a callable that returns an ArgumentParser :param ns_provider: An optional function that accepts a cmd2.Cmd or cmd2.CommandSet object as an argument and returns an @@ -327,7 +327,8 @@ def do_argprint(self, args, unknown): import functools def arg_decorator(func: ArgparseCommandFunc[CommandParent]) -> RawCommandFuncOptionalBoolReturn[CommandParent]: - """Decorator function that ingests an Argparse Command Function and returns a raw command function. + """Decorate function that ingests an Argparse Command Function and returns a raw command function. + The returned function will process the raw input into an argparse Namespace to be passed to the wrapped function. :param func: The defined argparse command function diff --git a/cmd2/history.py b/cmd2/history.py index 621b9416..1a8582b6 100644 --- a/cmd2/history.py +++ b/cmd2/history.py @@ -156,6 +156,7 @@ class to gain access to the historical record. _history_items_field = 'history_items' def __init__(self, seq: Iterable[HistoryItem] = ()) -> None: + """Initialize History instances.""" super().__init__(seq) self.session_start_index = 0 diff --git a/cmd2/py_bridge.py b/cmd2/py_bridge.py index aecf04f9..2a147583 100644 --- a/cmd2/py_bridge.py +++ b/cmd2/py_bridge.py @@ -87,6 +87,7 @@ class PyBridge: """ def __init__(self, cmd2_app: 'cmd2.Cmd', *, add_to_history: bool = True) -> None: + """Initialize PyBridge instances.""" self._cmd2_app = cmd2_app self._add_to_history = add_to_history self.cmd_echo = False diff --git a/cmd2/transcript.py b/cmd2/transcript.py index 9d376d8e..05c5db6c 100644 --- a/cmd2/transcript.py +++ b/cmd2/transcript.py @@ -42,6 +42,7 @@ class Cmd2TestCase(unittest.TestCase): cmdapp: Optional['Cmd'] = None def setUp(self) -> None: + """Instructions that will be executed before each test method.""" if self.cmdapp: self._fetch_transcripts() @@ -50,11 +51,13 @@ def setUp(self) -> None: self.cmdapp.stdout = cast(TextIO, utils.StdSim(cast(TextIO, self.cmdapp.stdout))) def tearDown(self) -> None: + """Instructions that will be executed after each test method.""" if self.cmdapp: # Restore stdout self.cmdapp.stdout = self._orig_stdout def runTest(self) -> None: # was testall # noqa: N802 + """Override of the default runTest method for the unittest.TestCase class.""" if self.cmdapp: its = sorted(self.transcripts.items()) for fname, transcript in its: diff --git a/cmd2/utils.py b/cmd2/utils.py index 7a90120e..84751723 100644 --- a/cmd2/utils.py +++ b/cmd2/utils.py @@ -528,6 +528,7 @@ def line_buffering(self) -> bool: return False def __getattr__(self, item: str) -> Any: + """When an attribute lookup fails to find the attribute in the usual places, this special method is called.""" if item in self.__dict__: return self.__dict__[item] return getattr(self.inner_stream, item) @@ -540,6 +541,7 @@ class ByteBuf: NEWLINES = (b'\n', b'\r') def __init__(self, std_sim_instance: StdSim) -> None: + """Initialize the ByteBuf instance.""" self.byte_buf = bytearray() self.std_sim_instance = std_sim_instance @@ -671,17 +673,22 @@ class ContextFlag: """ def __init__(self) -> None: - # When this flag has a positive value, it is considered set. - # When it is 0, it is not set. It should never go below 0. + """When this flag has a positive value, it is considered set. When it is 0, it is not set. + + It should never go below 0. + """ self.__count = 0 def __bool__(self) -> bool: + """Define the truth value of an object when it is used in a boolean context.""" return self.__count > 0 def __enter__(self) -> None: + """When a with block is entered, the __enter__ method of the context manager is called.""" self.__count += 1 def __exit__(self, *args: object) -> None: + """When the execution flow exits a with statement block this is called, regardless of whether an exception occurred.""" self.__count -= 1 if self.__count < 0: raise ValueError("count has gone below 0") @@ -1224,8 +1231,10 @@ def strip_doc_annotations(doc: str) -> str: def similarity_function(s1: str, s2: str) -> float: - # The ratio from s1,s2 may be different to s2,s1. We keep the max. - # See https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.ratio + """Ratio from s1,s2 may be different to s2,s1. We keep the max. + + See https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.ratio + """ return max(SequenceMatcher(None, s1, s2).ratio(), SequenceMatcher(None, s2, s1).ratio()) diff --git a/pyproject.toml b/pyproject.toml index 17a5ba91..1a550c40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -168,7 +168,7 @@ select = [ "C90", # McCabe cyclomatic complexity (warn about functions that are too complex) "COM", # flake8-commas (forces commas at the end of every type of iterable/container # "CPY", # flake8-copyright (warn about missing copyright notice at top of file - currently in preview) - # "D", # pydocstyle (warn about things like missing docstrings) + "D", # pydocstyle (warn about things like missing docstrings) # "DOC", # pydoclint (docstring warnings - currently in preview) # "DJ", # flake8-django (Django-specific warnings) "DTZ", # flake8-datetimez (warn about datetime calls where no timezone is specified)