Source code for statsmodels.tools.docstring_helpers

"""
Vendored docstring decorators

Previously imported from pandas.util._decorators. No longer depend on
pandas internals.

Originally derived from matplotlib.docstring (1.1.0). Vendored to remove
statsmodels' dependency on pandas private API.
"""

from __future__ import annotations

from textwrap import dedent


[docs] class Appender: """ A function decorator that will append an addendum to the docstring of the target function This decorator is robust even if func.__doc__ is None (for example, if -OO was passed to the interpreter). Parameters ---------- addendum : str or None String to append to the wrapped function's docstring. join : str, optional A string placed between the original docstring and the addendum. Default is "". indents : int, optional Number of indents (4-space blocks) added to all lines of the addendum. Default is 0. Examples -------- Usage: construct an Appender with a string to be joined to the original docstring. An optional 'join' parameter may be supplied which will be used to join the docstring and addendum. e.g. >>> add_copyright = Appender("Copyright (c) 2009", join=" ") >>> @add_copyright ... def my_dog(has='fleas'): ... "This docstring will have a copyright notice appended to it." ... pass """ addendum: str | None def __init__(self, addendum: str | None, join: str = "", indents: int = 0) -> None: if indents > 0: self.addendum = indent(addendum, indents=indents) else: self.addendum = addendum self.join = join def __call__(self, func): func.__doc__ = func.__doc__ or "" self.addendum = self.addendum or "" docitems = [func.__doc__, self.addendum] func.__doc__ = dedent(self.join.join(docitems)) return func
[docs] class Substitution: """ A decorator to take a function's docstring and perform string substitution on it This decorator is robust even if func.__doc__ is None (for example, if -OO was passed to the interpreter). Parameters ---------- *args : str Positional arguments for %s-style substitution. **kwargs : str Keyword arguments for %(name)s-style substitution. Cannot be combined with positional args. Examples -------- Usage: construct a Substitution with a sequence or dictionary suitable for performing substitution; then decorate a suitable function with the constructed object. e.g. >>> sub_author_name = Substitution(author='Jason') >>> @sub_author_name >>> def some_function(x): ... "%(author)s wrote this function" Note that some_function.__doc__ is now "Jason wrote this function" One can also use positional arguments: >>> sub_first_last_names = Substitution('Edgar Allen', 'Poe') >>> @sub_first_last_names >>> def some_function(x): ... "%s %s wrote the Raven" """ def __init__(self, *args: object, **kwargs: object) -> None: if args and kwargs: raise AssertionError("Only positional or keyword args are allowed") self.params: tuple | dict = args or kwargs def __call__(self, func): func.__doc__ = func.__doc__ and func.__doc__ % self.params return func
[docs] def update(self, *args: object, **kwargs: object) -> None: """ Update self.params with supplied args Only valid when Substitution was constructed with keyword arguments (i.e. self.params is a dict). No-op for positional (tuple) params. """ if isinstance(self.params, dict): self.params.update(*args, **kwargs)
[docs] def indent(text: str | None, indents: int = 1) -> str: """ Add indentation to each line of text Uses 4-space blocks per indent level, matching pandas' original behavior. Parameters ---------- text : str or None The text to indent. Returns "" if None or empty. indents : int, optional Number of 4-space indent levels to add. Default is 1. Returns ------- str Indented text, or "" if input was None/empty. """ if not text or not isinstance(text, str): return "" jointext = "".join(["\n"] + [" "] * indents) return jointext.join(text.split("\n"))