File: generate_datastream

package info (click to toggle)
morse-simulator 1.4-8
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 187,116 kB
  • sloc: ansic: 108,311; python: 25,694; cpp: 786; makefile: 126; xml: 34; sh: 7
file content (155 lines) | stat: -rwxr-xr-x 4,005 bytes parent folder | download | duplicates (4)
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
#! /usr/bin/env python3
"""
This tools generates documentation in RST format based on the Python source for
datastream modules.
"""

import sys
import pkgutil
import inspect

#
# helpers
#

def get_classes_from_module(module_name):
    __import__(module_name)
    # Predicate to make sure the classes only come from the module in question
    def predicate(member):
        return inspect.isclass(member) and member.__module__.startswith(module_name)
    # fetch all members of module name matching 'pred'
    return inspect.getmembers(sys.modules[module_name], predicate)

def get_submodules(module_name):
    """ Get a list of submodules from a module name.
    Not recursive, don't return nor look in subpackages """
    __import__(module_name)
    module = sys.modules[module_name]
    module_path = getattr(module, '__path__')
    return [name for _, name, ispkg in pkgutil.iter_modules(module_path) if not ispkg]

def get_subclasses(module_name, skip_submodules=[]):
    subclasses = []
    submodules = get_submodules(module_name)
    for submodule_name in submodules:
        if submodule_name in skip_submodules:
            pass
        submodule = "%s.%s"%(module_name, submodule_name)
        try:
            submodule_classes = get_classes_from_module(submodule)
            for _, klass in submodule_classes:
                subclasses.append(klass)
        except Exception:
            # can not import some resources
            pass
    return subclasses


#
# builder
#

data_builder = {
    'Robots': 'morse.builder.robots',
    'Sensors': 'morse.builder.sensors',
    'Actuators': 'morse.builder.actuators',
}

MORSE_DOC_BUILDER_MODULES = """
%(section)s
%(tag)s

**module** : ``%(module)s``

%(doc)s
"""

MORSE_DOC_BUILDER = """
List of classes
===============

%s
"""

def doclist_class_name(module):
    classes = get_classes_from_module(module)
    # getmembers returns a list of (name, value)
    return '\n'.join(["- %s"%name for name, klass in classes])

def doc_morse_builder_modules():
    for section, module in data_builder.items():
        yield {
            'section': section,
            'tag': '-' * len(section),
            'module': module,
            'doc': doclist_class_name(module),
        }

def doc_morse_builder():
    return MORSE_DOC_BUILDER % '\n'.join([MORSE_DOC_BUILDER_MODULES % doc for doc in
            doc_morse_builder_modules()])


#
# datastream
#

data_datastream = {
    'ROS' : 'morse.middleware.ros',
}

MORSE_DOC_DATASTERAM_CLASS = """
%(module_name)s.%(class_name)s
------------------------------

**type** : `%(type_name)s<%(type_url)s>`_

%(class_doc)s
"""

def doc_morse_datastream_class(module_name, skip_submodules=[]):
    subclasses = get_subclasses(module_name, skip_submodules)
    for klass in subclasses:
        try:
            yield {
                'class_name': klass.__name__,
                'module_name': klass.__module__,
                'class_doc': klass.__doc__,
                'type_url': klass._type_url,
                'type_name': klass._type_name,
            }
        except AttributeError:
            # not a datastream class
            pass

def doc_morse_datastream(datastream):
    doc = doc_morse_datastream_class(data_datastream[datastream])
    return '\n'.join([MORSE_DOC_DATASTERAM_CLASS % cls for cls in doc])


#
# main
#

def main(args):
    if 'datastream' in args:
        echo_off = sys.stdout
        sys.stdout = None # disable print in following
        doc_str = doc_morse_datastream('ROS')
        sys.stdout = echo_off # re-enable print
        print(doc_str)
        return 0
    if 'builder' in args:
        echo_off = sys.stdout
        sys.stdout = None # disable print in following
        doc_str = doc_morse_builder()
        sys.stdout = echo_off # re-enable print
        print(doc_str)
        return 0
    print("usage:")
    print("%s [datastream|builder] > doc.rst"%args[0])
    return 2 # incorrect usage


if __name__ == '__main__':
    sys.exit(main(sys.argv))