3

I would like to print the documentation for a module to include docstrings for each class and each method within the class, but only including methods I have written; not default methods.

This is my_module.py:

import json
import pandas as pd

class my_class1:
    """My class 1 docs."""

    def my_method1(self):
        """My class 1 method 1 docs."""
        return None

class my_class2:
    """My class 1 docs."""

    def my_method1(self):
        """My class 2 method 2 docs."""
        return None

Desired Output is this:

my_class1
My class 1 docs.

    my_method1:
    My class 1 method 1 docs.


my_class2
My class 2 docs.

    my_method2:
    My class 2 method 2 docs.

This script successfully prints all the class methods that I want:

import my_module as mm
imports = ['json','pd']  # Pre-defined modules within my_module that I don't wish to document
for i in [c for c in dir(mm) if not c.startswith('__') and not c in imports]:
    print(getattr(mm, i).__name__)
    print(getattr(mm, i).__doc__)

Output:

my_class1
My class 1 docs.
my_class2
My class 1 docs.

But I have tried this script to include methods but it just documents each class multiple times and excludes the methods.

import my_module as mm
imports = ['json','pd']
for i in [c for c in dir(mm) if not c.startswith('__') and not c in imports]:
        print(getattr(mm, i).__name__)
        print(getattr(mm, i).__doc__)
        for j in [c for c in dir(i) if c == '__init__' or not c.startswith('__')]:
             print(getattr(mm, i,j).__name__)
             print(getattr(mm, i,j).__doc__)

Output:

my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class1
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.
my_class2
My class 1 docs.

What should I use to print all the method docstrings?

doctorer
  • 1,672
  • 5
  • 27
  • 50

1 Answers1

1

Here is a solution that heavily uses the inspect module. Note that this only goes 2 layers deep. It will not catch methods nested inside other class methods. I tested it on quite a few of the included packages, and had good results.

import inspect


def is_relevant(obj):
    """Filter for the inspector to filter out non user defined functions/classes"""
    if hasattr(obj, '__name__') and obj.__name__ == 'type':
        return False
    if inspect.isfunction(obj) or inspect.isclass(obj) or inspect.ismethod(obj):
        return True


def print_docs(module):
    default = 'No doc string provided' # Default if there is no docstring, can be removed if you want
    flag = True

    for child in inspect.getmembers(module, is_relevant):
        if not flag: print('\n\n\n')
        flag = False # To avoid the newlines at top of output
        doc = inspect.getdoc(child[1])
        if not doc:
            doc = default
        print(child[0], doc, sep = '\n')

        if inspect.isclass(child[1]):
            for grandchild in inspect.getmembers(child[1], is_relevant):
                doc = inspect.getdoc(grandchild[1])
                if doc:
                    doc = doc.replace('\n', '\n    ')
                else:
                    doc = default 
                print('\n    ' + grandchild[0], doc, sep = '\n    ')


import your_module
print_docs(your_module)
Robert Kearns
  • 1,631
  • 1
  • 8
  • 15