"...ssh:/git@developer.sourcefind.cn:2222/tsoc/openmm.git" did not exist on "f025c5f4175e8a7e70ea11002186ad948442d71f"
render.py 4.17 KB
Newer Older
Robert McGibbon's avatar
Robert McGibbon committed
1
2
3
4
5
"""
The function of this script is to render the Jinja2 templates in the current
directory into input files for sphinx. It introspects the OpenMM Python module
to find all of the classes and formats them for inclusion into the templates.
"""
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
6
7
8
9
10
from os.path import dirname, join, splitext
from glob import glob
import inspect

import jinja2
Robert McGibbon's avatar
Robert McGibbon committed
11
12
import simtk.openmm.openmm
import simtk.openmm.app
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
13
14
15
16
17

def fullname(klass):
    return klass.__module__ + '.' + klass.__name__


18
def library_template_variables():
Robert McGibbon's avatar
Robert McGibbon committed
19
20
21
22
23
24
25
26
27
28
    """Create the data structure available to the Jinja2 renderer when
    filling in the templates.

    This function extracts all of classes in ``simtk.openmm.openmm`` and returns
    a dictionary with them grouped into three lists, the integrators, the forces,
    and the remainder (library_extras).

    A couple core classes are skipped, because they're included manually in the
    template.
    """
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
29
30
    data = {
        'integrators': [],
31
        'forces': [],
Robert McGibbon's avatar
Robert McGibbon committed
32
        'library_extras': [],
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
33
34
    }

Robert McGibbon's avatar
Robert McGibbon committed
35
    mm_klasses = inspect.getmembers(simtk.openmm.openmm, predicate=inspect.isclass)
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
36
37
38
39
40
41
42
43
44
45
46

    # gather all Force subclasses
    for name, klass in mm_klasses:
        if issubclass(klass, mm.Force):
            data['forces'].append(fullname(klass))

    # gather all Integrator subclasses
    for _, klass in mm_klasses:
        if issubclass(klass, mm.Integrator):
            data['integrators'].append(fullname(klass))

47
    # gather all extra subclasses in simtk.openmm.openmm
Robert McGibbon's avatar
Robert McGibbon committed
48
49

    # core classes that are already included in library.rst.jinja2
50
51
52
53
    exclude = ['simtk.openmm.openmm.Platform', 'simtk.openmm.openmm.Context',
              'simtk.openmm.openmm.System', 'simtk.openmm.openmm.State']
    exclude.extend(data['forces'])
    exclude.extend(data['integrators'])
Robert McGibbon's avatar
Robert McGibbon committed
54
55

    # these classes are useless and not worth documenting.
56
57
58
59
    exclude.extend([
        'simtk.openmm.openmm.SwigPyIterator',
        'simtk.openmm.openmm.OpenMMException'])

Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
60
61
    for _, klass in mm_klasses:
        full = fullname(klass)
62
63
64
65
        if full not in exclude and not klass.__name__[0].islower():
            data['library_extras'].append(full)

    return data
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
66
67


68
def app_template_variables():
Robert McGibbon's avatar
Robert McGibbon committed
69
70
71
72
73
74
75
76
77
78
    """Create the data structure available to the Jinja2 renderer when
    filling in the templates.

    This function extracts all of classes in ``simtk.openmm.app`` and returns
    a dictionary with them grouped into three lists, the reporters, the
    classes with the word "File" in the name, and the remainder.

    Four classes are skipped (see exclude), because they're included manually
    in the template.
    """
79
80
81
82
83
84
    data = {
        'reporters': [],
        'fileclasses': [],
        'app_extras': [],
    }

Robert McGibbon's avatar
Robert McGibbon committed
85
    app_klasses = inspect.getmembers(simtk.openmm.app, predicate=inspect.isclass)
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

    # gather all Reporters
    for name, klass in app_klasses:
        if name.endswith('Reporter'):
            data['reporters'].append(fullname(klass))

    # gather all classes with "File" in the name
    for name, klass in app_klasses:
        if 'File' in name:
            data['fileclasses'].append(fullname(klass))

    # gather all extra subclasses in simtk.openmm.app
    exclude = ['simtk.openmm.app.topology.Topology',
               'simtk.openmm.app.modeller.Modeller',
               'simtk.openmm.app.forcefield.ForceField',
               'simtk.openmm.app.simulation.Simulation']
    exclude.extend(data['reporters'])
    exclude.extend(data['fileclasses'])

    for _, klass in app_klasses:
        full = fullname(klass)
        if full not in exclude and not klass.__name__[0].islower():
            data['app_extras'].append(full)
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
109
110
111
112
113
114
115
116

    return data


def main():
    here = dirname(__file__)
    templateLoader = jinja2.FileSystemLoader(here)
    templateEnv = jinja2.Environment(loader=templateLoader)
117
118
    data = library_template_variables()
    data.update(app_template_variables())
Robert McGibbon's avatar
Sphinx  
Robert McGibbon committed
119
120
121
122
123
124
125
126
127
128
129
130
131

    for template_fn in glob(join(here, '*.jinja2')):
        output_fn = splitext(template_fn)[0]
        print('Rendering %s to %s...' % (template_fn, output_fn))

        template = templateEnv.get_template(template_fn)
        output_text = template.render(data)
        with open(output_fn, 'w') as f:
            f.write(output_text)


if __name__ == '__main__':
    main()