Docstring generator in Google type
if (&quot;Summary&quot; in config) and (config[&quot;Summary&quot;] is not None):


Can be simplified to:
if config.get(&quot;summary&quot;) is not None:




args = [&quot;Args:&quot;] + [f&quot;\t{arg}: Function argument&quot; for arg in config[&quot;Args&quot;]]
attr = [&quot;Attributes:&quot;] + [f&quot;\t{attr}: Information about parameter {attr}&quot; for attr in config[&quot;Attributes&quot;]]
todo = [&quot;Todo:&quot;] + [f&quot;\t{star} {todo}&quot; for todo in config[&quot;Todo&quot;]]


Can all be moved into a function.

You always add f&quot;{Name}:&quot;,
You always iterate through config[Name], and
You always format the value. Which can be provided as a format string (not an f-string).

def format_values(config, name, fmt):
    return [f&quot;{name}:&quot;] + [fmt.format(value) for value in config[name]]

format_values(config, &quot;Args&quot;, &quot;\t{}: Function argument&quot;)




docstring.append(config[&quot;Summary&quot;])
raises = [&quot;Raises: &quot;] + [f&quot;\t {config.get('Raises')}&quot;]
returns = [&quot;Returns: &quot;] + [f&quot;\t {config.get('Returns')}&quot;]


Can all be moved into a function.

You add f&quot;{Name}: &quot; except for Summary,
You always add config[Name], and
You always format the value. (Summary would be &quot;{}&quot;)

def format_value(config, name, fmt, head=True):
    return ([f&quot;{name}: &quot;] if head else []) + [fmt.format(config[name])]

format_value(config, &quot;Summary&quot;, &quot;{}&quot;, False)




value = config.get('Description')
wrapper=textwrap.TextWrapper(subsequent_indent= '\t', width = 120)
description = [&quot;Description: &quot;] + [f&quot;\t{wrapper.fill(value)}&quot;]
docstring += description


To be able to handle Description we can change format_value (and optionally format_values for consistency) to take a lambda to decide how to display the value.
def format_value(config, name, fmt, head=True):
    return ([f&quot;{name}: &quot;] if head else []) + [fmt(config[name])]

wrapper = textwrap.TextWrapper(subsequent_indent='\t', width=120)
docstring += format_value(config, &quot;Description&quot;, lambda value: f&quot;\t{wrapper.fill(value)}&quot;)



Lets look at how the code looks now:
import textwrap


def format_value(config, name, fmt, head=True):
    return ([f&quot;{name}: &quot;] if head else []) + [fmt(config[name])]


def format_values(config, name, fmt):
    return [f&quot;{name}:&quot;] + [fmt(value) for value in config[name]]


def gendoc(config):
    docstring = []
    if None is not config.get(&quot;Summary&quot;):
        docstring += format_value(config, &quot;Summary&quot;, lambda summary: summary, False)
    if None is not config.get(&quot;Args&quot;):
        docstring += format_values(config, &quot;Args&quot;, lambda arg: f&quot;\t{arg}: Function argument&quot;)
    if None is not config.get(&quot;Attributes&quot;):
        docstring += format_values(config, &quot;Attributes&quot;, lambda attr: f&quot;\t{arg}: Information about parameter {arg}&quot;)
    if None is not config.get(&quot;Raises&quot;):
        docstring += format_value(config, &quot;Raises&quot;, lambda raises: f&quot;\t {raises}&quot;)
    if None is not config.get(&quot;Returns&quot;):
        docstring += format_value(config, &quot;Returns&quot;, lambda returns: f&quot;\t {returns}&quot;)
    if None is not config.get(&quot;Description&quot;):
        wrapper = textwrap.TextWrapper(subsequent_indent='\t', width=120)
        docstring += format_value(config, &quot;Description&quot;, lambda value: f&quot;\t{wrapper.fill(value)}&quot;)
    if None is not config.get(&quot;Todo&quot;):
        star = &quot;*&quot;
        docstring += format_values(config, &quot;Todo&quot;, lambda todo: f&quot;\t{star} {todo}&quot;)

    docstring = &quot;\n\n&quot;.join(docstring)
    return docstring


if None is not config.get({name}):
    docstring += format_value(config, {name}, ...)


We can see we are duplicating the above pseudocode.
Lets ignore the fmt and head arguments to format_value and format_values.
We could change the code to:
docstring = []
for name, fn in ...:
    if config.get(name) is not None:
        docstring += fn(config, name)

We can change format_value and format_values so we provide the fmt and head.
We then return another function which takes config and name to call in the loop.
def format_value(fmt, head=True):
    def inner(config, name):
        return ([f&quot;{name}: &quot;] if head else []) + [fmt(config[name])]
    return inner

format_value(&quot;{}&quot;)(config, &quot;Summary&quot;)

Next we can define a dictionary to store the result of the first call to format_value and format_values.
And then change the code to iterate over the dictionary.
Final code:
import textwrap


def format_value(fmt, head=True):
    def inner(config, name):
        return ([f&quot;{name}: &quot;] if head else []) + [fmt(config[name])]
    return inner


def format_values(fmt):
    def inner(config, name):
        return [f&quot;{name}:&quot;] + [fmt(value) for value in config[name]]
    return inner


wrapper = textwrap.TextWrapper(subsequent_indent='\t', width=120)
star = &quot;*&quot;

FORMATS = {
    &quot;Summary&quot;: format_value(lambda summary: f&quot;{summary}&quot;, False),
    &quot;Args&quot;: format_values(lambda arg: f&quot;\t{arg}: Function argument&quot;),
    &quot;Attributes&quot;: format_values(lambda attr: f&quot;\t{arg}: Information about parameter {arg}&quot;),
    &quot;Raises&quot;: format_value(lambda raises: f&quot;\t {raises}&quot;),
    &quot;Returns&quot;: format_value(lambda returns: f&quot;\t {returns}&quot;),
    &quot;Description&quot;: format_value(lambda value: f&quot;\t{wrapper.fill(value)}&quot;),
    &quot;Todo&quot;: format_values(lambda todo: f&quot;\t{star} {todo}&quot;),
}


def gendoc(config):
    docstring = []
    for name, fn in FORMATS.items():
        if config.get(name) is not None:
            docstring += fn(config, name)
    return &quot;\n\n&quot;.join(docstring)