summaryrefslogtreecommitdiff
path: root/doc/ext/versioned_notifications.py
blob: c3fe54aca0300f8d3a6b389bec12e23ec7fc287a (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
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""
This provides a sphinx extension able to list the implemented versioned
notifications into the developer documentation.

It is used via a single directive in the .rst file

  .. versioned_notifications::

"""

from sphinx.util.compat import Directive
from docutils import nodes

from nova.notifications.objects import base as notification
from nova.objects import base
# Make sure that all the notification classes are defined so the
# registration mechanism can pick them up later.
from nova.notifications.objects import exception
from nova.notifications.objects import flavor
from nova.notifications.objects import instance
from nova.notifications.objects import service


class VersionedNotificationDirective(Directive):

    SAMPLE_ROOT = 'doc/notification_samples/'
    TOGGLE_SCRIPT = """
<script>
jQuery(document).ready(function(){
    jQuery('#%s-div').toggle('show');
    jQuery('#%s-hideshow').on('click', function(event) {
        jQuery('#%s-div').toggle('show');
    });
});
</script>
"""

    def run(self):
        notifications = self._collect_notifications()
        return self._build_markup(notifications)

    def _collect_notifications(self):
        base.NovaObjectRegistry.register_notification_objects()
        notifications = []
        ovos = base.NovaObjectRegistry.obj_classes()
        for name, cls in ovos.items():
            cls = cls[0]
            if (issubclass(cls, notification.NotificationBase) and
                    cls != notification.NotificationBase):

                payload_name = cls.fields['payload'].objname
                payload_cls = ovos[payload_name][0]
                for sample in cls.samples:
                    notifications.append((cls.__name__,
                                          payload_cls.__name__,
                                          sample))
        return sorted(notifications)

    def _build_markup(self, notifications):
        content = []
        cols = ['Event type', 'Notification class', 'Payload class', 'Sample']
        table = nodes.table()
        content.append(table)
        group = nodes.tgroup(cols=len(cols))
        table.append(group)

        head = nodes.thead()
        group.append(head)

        for _ in cols:
            group.append(nodes.colspec(colwidth=1))

        body = nodes.tbody()
        group.append(body)

        # fill the table header
        row = nodes.row()
        body.append(row)
        for col_name in cols:
            col = nodes.entry()
            row.append(col)
            text = nodes.strong(text=col_name)
            col.append(text)

        # fill the table content, one notification per row
        for name, payload, sample_file in notifications:
            event_type = sample_file[0: -5].replace('-', '.')

            row = nodes.row()
            body.append(row)
            col = nodes.entry()
            row.append(col)
            text = nodes.literal(text=event_type)
            col.append(text)

            col = nodes.entry()
            row.append(col)
            text = nodes.literal(text=name)
            col.append(text)

            col = nodes.entry()
            row.append(col)
            text = nodes.literal(text=payload)
            col.append(text)

            col = nodes.entry()
            row.append(col)

            with open(self.SAMPLE_ROOT + sample_file, 'r') as f:
                sample_content = f.read()

            event_type = sample_file[0: -5]
            html_str = self.TOGGLE_SCRIPT % ((event_type, ) * 3)
            html_str += ("<input type='button' id='%s-hideshow' "
                         "value='hide/show sample'>" % event_type)
            html_str += ("<div id='%s-div'><pre>%s</pre></div>"
                         % (event_type, sample_content))

            raw = nodes.raw('', html_str, format="html")
            col.append(raw)

        return content


def setup(app):
    app.add_directive('versioned_notifications',
                      VersionedNotificationDirective)