Search code examples
pythondocstring

how to dynamically change indentation in a multiline string?


I'm using docstrings to document my code with Sphinx. I recently started to use ruff to lint my code and It is by default applying D212 instead of D213. The only difference being that the first line of the docstring (short description) must start on the first line.

It breaks one of the decorator that I'm using (deprecated) as it cannot handle both types. The decorator handles docstring as followed:

docstring = textwrap.dedent(wrapped.__doc__ or "")
# do stuff with docstring 

How can I update the docstring parsing to handle docstring starting on a newline (D213) and starting on the first line (D212) the same way ?

# respecting D213
def func_a():
    """
    one liner
    
    Args: 
        toto
    """

# respecting D212
def func_a():
    """one liner 
    
    Args: 
        toto
    """

I tried to manipulate func_b.__doc__ in combination with dedent with no success.


Solution

  • After some digging I came up with the following code:

    docstring = func_b.__doc__ or ""
    lines = docstring.splitlines(keepends=True) or [""]
    docstring = textwrap.dedent("".join(lines[1:])) if len(lines) > 1 else ""
    docstring = lines[0] + docstring
    

    If I feed this with func_a it remains unchanged and with func_b the indentation is set back at the start. bonus: it works as well with 1-liner docstrings.