jdkandersson / flake8-docstrings-complete

Apache License 2.0
12 stars 3 forks source link

flake8-docstrings-complete

Linter that checks docstrings of functions, methods and classes. It should be used in conjunction with pydocstyle (or flake8-docstrings) as the linter assumes that the docstrings already pass pydocstyle checks. This blog post discusses how to write great docstrings and the motivation for this linter!

Following PEP-8, Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does. The definition taken for private functions/methods is that they start with a single underscore (_).

Getting Started

python -m venv venv
source ./venv/bin/activate
pip install flake8 flake8-docstrings flake8-docstrings-complete
flake8 source.py

On the following code where the foo function has the bar and baz arguments where the baz argument is missing from the Args section in the docstring:

# source.py
def foo(bar, baz):
    """Perform foo action on bar.

    Args:
        bar: The value to perform the foo action on.
    """

This will produce warnings such as:

flake8 test_source.py
source.py:2:14: DCO023 "baz" argument should be described in the docstring, more information: https://github.com/jdkandersson/flake8-docstrings-complete#fix-dco023

This can be resolved by adding the baz argument to the Args section:

# source.py
def foo(bar, baz):
    """Perform foo action on bar.

    Args:
        bar: The value to perform the foo action on.
        baz: The modifier to the foo action.
    """

flake8-docstrings-complete adds the following checks to complement pydocstyle:

  1. If a function/ method has arguments, that the arguments section is included.
  2. If a function/ method has arguments, that all function/ method arguments are in the argument section.
  3. If an arguments section is in the function/ method docstring, the argument section contains no arguments the function/ method doesn't have.
  4. Function/ method arguments are only documented once.
  5. If a function/ method has a return statement with a value, the return value section is included.
  6. If a function/ method has a yield statement with a value, the yield value section is included.
  7. If a function/ method raises an exception, the raises section is included with a description for each exception that is raised.
  8. Each raised exception is only described once.
  9. If a class has public attributes, that the attributes section is included.
  10. If a class has public attributes, that all public attributes are in the attributes section.
  11. If an attributes section is in the class docstring, the attributes section contains no attributes the class doesn't have.
  12. Class attributes are only documented once.
  13. Any of the sections being checked are not present multiple times.

Note:

Configuration

The plugin adds the following configurations to flake8:

Rules

A few rules have been defined to allow for selective suppression:

Fix DCO010

This linting rule is triggered by a function/ method/ class without a docstring. For example:

def foo():
    pass

class FooClass:
    def foo(self):
        """Perform foo action."""
        pass

class FooClass:
    """Perform foo action."""
    def foo(self):
        pass

This example can be fixed by adding a docstring:

def foo():
    """Perform foo action."""

class FooClass:
    """Perform foo action."""
    def foo(self):
        """Perform foo action."""

Fix DCO020

This linting rule is triggered by a function/ method that has one or more arguments with a docstring that does not have an arguments section. For example:

def foo(bar):
    """Perform foo action."""

class FooClass:
    def foo(self, bar):
        """Perform foo action."""

These examples can be fixed by adding the arguments section and describing all arguments in the arguments section:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

def foo(bar):
    """Perform foo action.

    Arguments:
        bar: the value to perform the foo action on.
    """

def foo(bar):
    """Perform foo action.

    Parameters:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
        """

Fix DCO021

This linting rule is triggered by a function/ method that has no arguments with a docstring that has an arguments section. For example:

def foo():
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

def foo():
    """Perform foo action.

    Arguments:
        bar: the value to perform the foo action on.
    """

def foo():
    """Perform foo action.

    Parameters:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
        """

These examples can be fixed by removing the arguments section:

def foo():
    """Perform foo action."""

class FooClass:
    def foo(self):
        """Perform foo action."""

Fix DCO022

This linting rule is triggered by a function/ method that has one or more arguments and a docstring that has multiple arguments sections. For example:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.

    Args:
        bar: the value to perform the foo action on.
    """

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.

    Arguments:
        bar: the value to perform the foo action on.

    Parameters:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.

        Args:
            bar: the value to perform the foo action on.
        """

These examples can be fixed by removing the additional arguments sections:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

def foo(bar):
    """Perform foo action.

    Arguments:
        bar: the value to perform the foo action on.
    """

def foo(bar):
    """Perform foo action.

    Parameters:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
        """

Fix DCO023

This linting rule is triggered by a function/ method that has one or more arguments where one or more of those arguments is not described in the docstring. For example:

def foo(bar):
    """Perform foo action.

    Args:
    """

def foo(bar, baz):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
        """

These examples can be fixed by adding the missing arguments to the arguments section:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

def foo(bar, baz):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
        baz: the modifier to the foo action.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
        """

Fix DCO024

This linting rule is triggered by a function/ method that has one or more arguments and a docstring that describes one or more arguments where on or more of the described arguments are not arguments of the function/ method. For example:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
        baz: the modifier to the foo action.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
            baz: the modifier to the foo action.
        """

These examples can be fixed by removing the arguments the function/ method doesn't have from the docstring:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
        """

Fix DCO025

This linting rule is triggered by a function/ method that has one or more arguments and a docstring that describes one or more arguments where on or more of the described arguments are described multiple times. For example:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
            bar: the value to perform the foo action on.
        """

These examples can be fixed by removing the duplicate arguments from the docstring:

def foo(bar):
    """Perform foo action.

    Args:
        bar: the value to perform the foo action on.
    """

class FooClass:
    def foo(self, bar):
        """Perform foo action.

        Args:
            bar: the value to perform the foo action on.
        """

Fix DCO030

This linting rule is triggered by a function/ method that has at least one return statement with a value and does not have a returns section in the docstring. For example:

def foo():
    """Return bar."""
    return "bar"

class FooClass:
    def foo(self):
        """Return bar."""
        return "bar"

These examples can be fixed by adding the returns section:

def foo():
    """Return bar.

    Return:
        bar.
    """
    return "bar"

def foo():
    """Return bar.

    Returns:
        bar.
    """
    return "bar"

class FooClass:
    def foo(self):
        """Return bar.

        Returns:
            bar.
        """
        return "bar"

Fix DCO031

This linting rule is triggered by a function/ method that has no return statement with a value and has a returns section in the docstring. For example:

def foo():
    """Return bar.

    Returns:
        bar.
    """
    pass

class FooClass:
    def foo(self):
        """Return bar.

        Returns:
            bar.
        """
        pass

These examples can be fixed by removing the returns section:

def foo():
    """Take foo action."""
    pass

class FooClass:
    def foo(self):
        """Take foo action."""
        pass

Fix DCO032

This linting rule is triggered by a function/ method that returns a value and has a docstring that has multiple returns sections. For example:

def foo():
    """Perform foo action.

    Returns:
        bar.

    Returns:
        bar.
    """
    return "bar"

def foo():
    """Perform foo action.

    Returns:
        bar.

    Return:
        bar.
    """
    return "bar"

class FooClass:
    def foo(self):
        """Perform foo action.

        Returns:
            bar.

        Returns:
            bar.
        """
        return "bar"

These examples can be fixed by removing the additional returns sections:

def foo():
    """Perform foo action.

    Returns:
        bar.
    """
    return "bar"

def foo():
    """Perform foo action.

    Returns:
        bar.
    """
    return "bar"

class FooClass:
    def foo(self):
        """Perform foo action.

        Returns:
            bar.
        """
        return "bar"

Fix DCO040

This linting rule is triggered by a function/ method that has at least one yield statement with a value or a yield from statement and does not have a yields section in the docstring. For example:

def foo():
    """Yield bar."""
    yield "bar"

def foo():
    """Yield bar."""
    yield from ("bar",)

class FooClass:
    def foo(self):
        """Yield bar."""
        yield "bar"

These examples can be fixed by adding the yields section:

def foo():
    """Yield bar.

    Yield:
        bar.
    """
    yield "bar"

def foo():
    """Yield bar.

    Yields:
        bar.
    """
    yield "bar"

def foo():
    """Yield bar.

    Yields:
        bar.
    """
    yield from ("bar",)

class FooClass:
    def foo(self):
        """Yield bar.

        Yields:
            bar.
        """
        yield "bar"

Fix DCO041

This linting rule is triggered by a function/ method that has no yield statement with a value nor a yield from statement and has a yields section in the docstring. For example:

def foo():
    """Yield bar.

    Yields:
        bar.
    """
    pass

class FooClass:
    def foo(self):
        """Yield bar.

        Yields:
            bar.
        """
        pass

These examples can be fixed by:

def foo():
    """Take foo action."""
    pass

class FooClass:
    def foo(self):
        """Take foo action."""
        pass

Fix DCO042

This linting rule is triggered by a function/ method that yields a value and has a docstring that has multiple yields sections. For example:

def foo():
    """Perform foo action.

    Yields:
        bar.

    Yields:
        bar.
    """
    yield "bar"

def foo():
    """Perform foo action.

    Yields:
        bar.

    Yields:
        bar.
    """
    yield from ("bar",)

def foo():
    """Perform foo action.

    Yields:
        bar.

    Yield:
        bar.
    """
    yield "bar"

class FooClass:
    def foo(self):
        """Perform foo action.

        Yields:
            bar.

        Yields:
            bar.
        """
        yield "bar"

These examples can be fixed by removing the additional yields sections:

def foo():
    """Perform foo action.

    Yields:
        bar.
    """
    yield "bar"

def foo():
    """Perform foo action.

    Yields:
        bar.
    """
    yield from ("bar",)

def foo():
    """Perform foo action.

    Yields:
        bar.
    """
    yield "bar"

class FooClass:
    def foo(self):
        """Perform foo action.

        Yields:
            bar.
        """
        yield "bar"

Fix DCO050

This linting rule is triggered by a function/ method that raises one or more exceptions and a docstring that does not have a raises section. For example:

def foo():
    """Perform foo action."""
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action."""
        raise BarError

These examples can be fixed by adding the raises section and describing all raised exceptions in it:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

def foo():
    """Perform foo action.

    Raise:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

Fix DCO051

This linting rule is triggered by a function/ method that raises no exceptions with a docstring that has a raises section. For example:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """

def foo():
    """Perform foo action.

    Raise:
        BarError: the value to perform the foo action on was wrong.
    """

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """

These examples can be fixed by removing the raises section:

def foo():
    """Perform foo action."""

class FooClass:
    def foo(self):
        """Perform foo action."""

Fix DCO052

This linting rule is triggered by a function/ method that raises one or more exceptions with a docstring that has multiple raises sections. For example:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.

    Raise:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

These examples can be fixed by removing the additional raises sections:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

def foo():
    """Perform foo action.

    Raise:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

Fix DCO053

This linting rule is triggered by a function/ method that raises one or more exceptions where one or more of those exceptions is not described in the docstring. For example:

def foo():
    """Perform foo action."""
    raise BarError

def foo(bar, baz):
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError
    raise BazError

class FooClass:
    def foo(self):
        """Perform foo action."""
        raise BarError

These examples can be fixed by describing the additional exceptions in the docstring:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

def foo(bar, baz):
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
        BazError: the alternate value to perform the foo action on was wrong.
    """
    raise BarError
    raise BazError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

Fix DCO054

This linting rule is triggered by a function/ method that raises one or more exceptions and a docstring that describes one or more exceptions where on or more of the described exceptions are not raised by the function/ method. For example:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
        BazError: the alternate value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
            BazError: the alternate value to perform the foo action on was wrong.
        """
        raise BarError

These examples can be fixed by removing the exception that is not raised from the docstring:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

Fix DCO055

This linting rule is triggered by a function/ method that has a raise statement without an exception (typically re-raising exceptions) and the raises section is not included or is empty. For example:

def foo():
    """Perform foo action."""
    try:
        bar()
    except BarError:
        raise

def foo():
    """Perform foo action.

    Raises:
    """
    try:
        bar()
    except BarError:
        raise

class FooClass:
    def foo(self):
        """Perform foo action."""
        try:
            bar()
        except BarError:
            raise

These examples can be fixed by describing at least one exception in the raises section:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    try:
        bar()
    except BarError:
        raise

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    try:
        bar()
    except BarError:
        raise

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        try:
            bar()
        except BarError:
            raise

Fix DCO056

This linting rule is triggered by a function/ method that raises one or more exceptions and a docstring that describes one or more exceptions where on or more of the described exceptions are described multiple times. For example:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

These examples can be fixed by removing the duplicate descriptions from the docstring:

def foo():
    """Perform foo action.

    Raises:
        BarError: the value to perform the foo action on was wrong.
    """
    raise BarError

class FooClass:
    def foo(self):
        """Perform foo action.

        Raises:
            BarError: the value to perform the foo action on was wrong.
        """
        raise BarError

Fix DCO060

This linting rule is triggered by a class that has one or more public attributes with a docstring that does not have an attributes section. For example:

class FooClass:
    """Perform foo action."""
    bar = "bar"

class FooClass:
    """Perform foo action."""

    def __init__(self):
        self.bar = "bar"

class FooClass:
    """Perform foo action."""

    def bar(self):
        self.baz = "baz"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"
    baz = "baz"

These examples can be fixed by adding the attributes section and describing all attributes in the attributes section:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attributes:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attributes:
        bar: The value to perform the foo action on.
    """

    def __init__(self):
        self.bar = "bar"

class FooClass:
    """Perform foo action.

    Attributes:
        baz: The value to perform the foo action on.
    """

    def bar(self):
        self.baz = "baz"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
        baz: The alternate value to perform the foo action on.
    """
    bar = "bar"
    baz = "baz"

Fix DCO061

This linting rule is triggered by a class that has no attributes with a docstring that has an attributes section. For example:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

class FooClass:
    """Perform foo action.

    Attributes:
        bar: The value to perform the foo action on.
    """

class FooClass:
    """Perform foo action.

    Attributes:
    """

    def __init__(self):
        self._bar = "bar"

These examples can be fixed by removing the attributes section:

class FooClass:
    """Perform foo action."""

class FooClass:
    """Perform foo action."""

    def __init__(self):
        self._bar = "bar"

Fix DCO062

This linting rule is triggered by a class that has one or more attributes and a docstring that has multiple attributes sections. For example:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.

    Attributes:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

These examples can be fixed by removing the additional attributes sections:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attributes:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

Fix DCO063

This linting rule is triggered by a class that has one or more public attributes where one or more of those public attributes is not described in the docstring. For example:

class FooClass:
    """Perform foo action."""
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attrs:
    """

    @property
    def bar(self):
        return "bar"

class FooClass:
    """Perform foo action.

    Attrs:
    """

    @functools.cached_property
    def bar(self):
        return "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"
    baz = "baz"

These examples can be fixed by adding the missing attributes to the attributes section:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attributes:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

    @property
    def bar(self):
        return "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

    @functools.cached_property
    def bar(self):
        return "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
        baz: The alternate value to perform the foo action on.
    """
    bar = "bar"
    baz = "baz"

Fix DCO064

This linting rule is triggered by a class that has one or more attributes and a docstring that describes one or more attributes where on or more of the described attributes are not attributes of the class. For example:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

class FooClass:
    """Perform foo action.

    Attrs:
        _bar: The value to perform the foo action on.
    """

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
        baz: The alternate value to perform the foo action on.
    """
    bar = "bar"

These examples can be fixed by removing the attributes the class doesn't have from the docstring:

class FooClass:
    """Perform foo action."""

class FooClass:
    """Perform foo action."""

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """
    bar = "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

    def __init__(self):
        """Construct."""
        self.bar = "bar"

Fix DCO065

This linting rule is triggered by a class that has one or more attributes and a docstring that describes one or more attributes where on or more of the described attributes are described multiple times. For example:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
        bar: The value to perform the foo action on.
    """

    bar = "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
        bar: The value to perform the foo action on.
    """

    def __init__(self):
        """Construct."""
        self.bar = "bar"

These examples can be fixed by removing the duplicate descriptions from the docstring:

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

    bar = "bar"

class FooClass:
    """Perform foo action.

    Attrs:
        bar: The value to perform the foo action on.
    """

    def __init__(self):
        """Construct."""
        self.bar = "bar"

Docstring Examples

Examples of function/ method and class docstrings are:

def foo(bar):
    """Perform the foo actions on bar.

    Args:
        bar: the value to perform the foo actions on.

    Returns:
        bar after applying to foo action to it.

    Yields:
        All the foo actions that have been performed.

    Raises:
        FooError: an error occurred whilst performing the foo action.
    """

class Foo:
    """Foo object.

    Attrs:
        bar: the value to perform the foo actions on.
    """

    def __init__(self, bar):
        """Construct.

        Args:
            bar: the value to perform the foo actions on.
        """
        self.bar = bar

Sections

There are several alternative names for each of the sections which are captured case-insensitive:

Section information is extracted using the following algorithm:

  1. Look for a line that has zero or more whitespace characters, followed by a section name (non-case-sensistive) followed by a colon.
  2. Look for any sub-sections on a line which starts with zero or more whitespace characters followed by a word, optionally followed by whitespace and any characters within round brackets followed by a colon.
  3. The section ends if any line with zero or more whitespace characters is encountered or the end of the docstring is reached.

Future Ideas: