summaryrefslogtreecommitdiff
path: root/doc/summarize.py
blob: 972e298f4f86e041057a67c4bd1bac38c4e95a8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env python
"""
summarize.py

Show a summary about which NumPy functions are documented and which are not.

"""
from __future__ import division, absolute_import, print_function

import os, glob, re, sys, inspect, optparse
try:
    # Accessing collections abstact classes from collections
    # has been deprecated since Python 3.3
    import collections.abc as collections_abc
except ImportError:
    import collections as collections_abc
sys.path.append(os.path.join(os.path.dirname(__file__), 'sphinxext'))
from sphinxext.phantom_import import import_phantom_module

from sphinxext.autosummary_generate import get_documented

CUR_DIR = os.path.dirname(__file__)
SOURCE_DIR = os.path.join(CUR_DIR, 'source', 'reference')

SKIP_LIST = """
# --- aliases:
alltrue sometrue bitwise_not cumproduct
row_stack column_stack product rank

# -- skipped:
core lib f2py dual doc emath ma rec char distutils oldnumeric numarray
testing version matlib

add_docstring add_newdoc add_newdocs fastCopyAndTranspose pkgload
conjugate disp

int0 object0 unicode0 uint0 string_ string0 void0

flagsobj

setup PackageLoader

lib.scimath.arccos lib.scimath.arcsin lib.scimath.arccosh lib.scimath.arcsinh
lib.scimath.arctanh lib.scimath.log lib.scimath.log2 lib.scimath.log10
lib.scimath.logn lib.scimath.power lib.scimath.sqrt

# --- numpy.random:
random random.info random.mtrand random.ranf random.sample random.random

# --- numpy.fft:
fft fft.Tester fft.bench fft.fftpack fft.fftpack_lite fft.helper
fft.info fft.test

# --- numpy.linalg:
linalg linalg.Tester
linalg.bench linalg.info linalg.lapack_lite linalg.linalg linalg.test

# --- numpy.ctypeslib:
ctypeslib ctypeslib.test

""".split()

def main():
    p = optparse.OptionParser(__doc__)
    p.add_option("-c", "--columns", action="store", type="int", dest="cols",
                 default=3, help="Maximum number of columns")
    options, args = p.parse_args()

    if len(args) != 0:
        p.error('Wrong number of arguments')

    # prepare
    fn = os.path.join(CUR_DIR, 'dump.xml')
    if os.path.isfile(fn):
        import_phantom_module(fn)

    # check
    documented, undocumented = check_numpy()

    # report
    in_sections = {}
    for name, locations in documented.items():
        for (filename, section, keyword, toctree) in locations:
            in_sections.setdefault((filename, section, keyword), []).append(name)

    print("Documented")
    print("==========\n")

    last_filename = None
    for (filename, section, keyword), names in sorted(in_sections.items()):
        if filename != last_filename:
            print("--- %s\n" % filename)
        last_filename = filename
        print(" ** ", section)
        print(format_in_columns(sorted(names), options.cols))
        print("\n")

    print("")
    print("Undocumented")
    print("============\n")
    print(format_in_columns(sorted(undocumented.keys()), options.cols))

def check_numpy():
    documented = get_documented(glob.glob(SOURCE_DIR + '/*.rst'))
    undocumented = {}

    import numpy, numpy.fft, numpy.linalg, numpy.random
    for mod in [numpy, numpy.fft, numpy.linalg, numpy.random,
                numpy.ctypeslib, numpy.emath, numpy.ma]:
        undocumented.update(get_undocumented(documented, mod, skip=SKIP_LIST))

    for d in (documented, undocumented):
        for k in d.keys():
            if k.startswith('numpy.'):
                d[k[6:]] = d[k]
                del d[k]

    return documented, undocumented

def get_undocumented(documented, module, module_name=None, skip=[]):
    """
    Find out which items in NumPy are not documented.

    Returns
    -------
    undocumented : dict of bool
        Dictionary containing True for each documented item name
        and False for each undocumented one.

    """
    undocumented = {}

    if module_name is None:
        module_name = module.__name__

    for name in dir(module):
        obj = getattr(module, name)
        if name.startswith('_'): continue

        full_name = '.'.join([module_name, name])

        if full_name in skip: continue
        if full_name.startswith('numpy.') and full_name[6:] in skip: continue
        if not (inspect.ismodule(obj) or isinstance(obj, collections_abc.Callable) or inspect.isclass(obj)):
            continue

        if full_name not in documented:
            undocumented[full_name] = True

    return undocumented

def format_in_columns(lst, max_columns):
    """
    Format a list containing strings to a string containing the items
    in columns.
    """
    lst = [str(_m) for _m in lst]
    col_len = max([len(_m) for _m in lst]) + 2
    ncols = 80//col_len
    if ncols > max_columns:
        ncols = max_columns
    if ncols <= 0:
        ncols = 1

    if len(lst) % ncols == 0:
        nrows = len(lst)//ncols
    else:
        nrows = 1 + len(lst)//ncols

    fmt = ' %%-%ds ' % (col_len-2)

    lines = []
    for n in range(nrows):
        lines.append("".join([fmt % x for x in lst[n::nrows]]))
    return "\n".join(lines)

if __name__ == "__main__": main()