File: progress.py

package info (click to toggle)
python-pgpy 0.6.0-1.4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,212 kB
  • sloc: python: 8,448; makefile: 155; sh: 10
file content (149 lines) | stat: -rw-r--r-- 4,910 bytes parent folder | download | duplicates (2)
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
__author__ = 'magreene'

import collections
import re

from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.statemachine import StringList


class progress(nodes.General, nodes.Element):
    tagname = 'progress'


class ProgressTable(Directive):
    has_content = True
    required_arguments = 1
    final_argument_whitespace = True
    option_spec = {'text': str}

    def create_headrow(self, label="Progress", classes=('prog-top-label',)):
        hrow = nodes.row()
        hrow += nodes.entry('', nodes.paragraph(text=label), classes=['head'] + list(classes))
        hrow += nodes.entry('', nodes.paragraph(text='PLACEHOLDER'), classes=['PLACEHOLDER'])
        return hrow

    def create_progtable(self, **attrs):
        _attrs = {
            'classes': ['progress', 'outer', 'docutils', 'field-list'],
            'colwidths': [20, 80]
        }
        _attrs.update(attrs)

        # create container elements
        node = nodes.table(classes=_attrs['classes'])
        tgroup = nodes.tgroup(cols=2)
        thead = thead = nodes.thead()
        thead += self.create_headrow()
        tbody = nodes.tbody()

        # tgroup gets:
        #  - colspec
        #  - thead
        #  - tbody
        for w in _attrs['colwidths']:
            tgroup += nodes.colspec(colwidth=w)

        # assemble the hierarchy
        tgroup += thead
        tgroup += tbody
        node += tgroup

        # return the table
        return node

    def add_progbar(self, row, val, max):
        entry = nodes.entry(classes=['progcell', 'field-value'])
        pbar = progress(value=val, max=max)
        entry += pbar

        row.replace(row.children[-1], entry)

    def run(self):
        secid = [self.arguments[0].lower().replace(' ', '-')]
        section = nodes.section(ids=secid)
        section.document = self.state.document

        section += nodes.title(text=self.arguments[0])

        # parse the 'text' option into the section, as a paragraph.
        self.state.nested_parse(StringList([self.options['text']], parent=self), 0, section)

        node = self.create_progtable()
        section.children[-1] += node

        head = node.children[0].children[-2].children[0]
        body = node.children[0].children[-1]

        comps = collections.OrderedDict()
        cur = ""

        for line in self.content:
            # new list
            nl = re.match(r'^:(?P<component>.+):$', line)
            if nl is not None:
                if cur != "":
                    # finish up shrow
                    self.add_progbar(shrow, len([c for c in comps[cur] if c is True]), len(comps[cur]))

                cur = nl.groupdict()['component']

                if cur not in comps:
                    comps[cur] = []

                # shrow is the section header row
                shrow = self.create_headrow(cur, classes=['field-name'])
                body += shrow

                continue

            nl = re.match(r'^\s+- (?P<item>[^,]+),\s+(?P<value>(True|False))(, (?P<description>.+)$)?', line)
            if nl is not None:
                nl = nl.groupdict()
                comps[cur].append(True if nl['value'] == "True" else False)
                tr = nodes.row()
                tr += nodes.description('',
                                        nodes.inline(text="\u2713" if comps[cur][-1] else " "),
                                        classes=['field-name', 'progress-checkbox'])
                text_description = nodes.inline()
                self.state.nested_parse(StringList(['{:s}'.format(nl['description'].lstrip() if nl['description'] is not None else ' ')], parent=self), 0, text_description)

                tr += nodes.description('',
                                        nodes.strong(text='{:s} '.format(nl['item'])),
                                        text_description,
                                        classes=['field-value'])
                body += tr

        if self.content:
            # finish up the final hrow
            self.add_progbar(shrow, len([c for c in comps[cur] if c == True]), len(comps[cur]))


        # and fill in the end of mrow
        self.add_progbar(head, len([c for r in comps.values() for c in r if c == True]), len([c for r in comps.values() for c in r]))


        return [section]


def visit_progress(self, node):
    attrs = {'value': 0,
             'max': 0}
    for a in attrs.keys():
        if a in node.attributes:
            attrs[a] = node.attributes[a]

    self.body.append('<label>{}/{}</label>'.format(attrs['value'], attrs['max']))
    self.body.append(self.starttag(node, node.tagname, **attrs))
    self.body.append('</progress>')


def depart_progress(self, node):
    pass


def setup(app):
    app.add_css_file('progress.css')
    app.add_node(progress, html=(visit_progress, depart_progress))
    app.add_directive('progress', ProgressTable)