aboutsummaryrefslogtreecommitdiff
path: root/proposals/reindex.py
blob: 980bc0659fbd96614648235620a6844e3878f545 (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
#!/usr/bin/python

import re, os
class Error(Exception): pass

STATUSES = """DRAFT NEEDS-REVISION NEEDS-RESEARCH OPEN ACCEPTED META FINISHED
   CLOSED SUPERSEDED DEAD REJECTED""".split()
REQUIRED_FIELDS = [ "Filename", "Status", "Title" ]
CONDITIONAL_FIELDS = { "OPEN" : [ "Target" ],
                       "ACCEPTED" : [ "Target "],
                       "CLOSED" : [ "Implemented-In" ],
                       "FINISHED" : [ "Implemented-In" ] }
FNAME_RE = re.compile(r'^(\d\d\d)-.*[^\~]$')
DIR = "."
OUTFILE = "000-index.txt"
TMPFILE = OUTFILE+".tmp"

def indexed(seq):
    n = 0
    for i in seq:
        yield n, i
        n += 1

def readProposal(fn):
    fields = { }
    f = open(fn, 'r')
    lastField = None
    try:
        for lineno, line in indexed(f):
            line = line.rstrip()
            if not line:
                return fields
            if line[0].isspace():
                fields[lastField] += " %s"%(line.strip())
            else:
                parts = line.split(":", 1)
                if len(parts) != 2:
                    raise Error("%s:%s:  Neither field nor continuation"%
                                (fn,lineno))
                else:
                    fields[parts[0]] = parts[1].strip()
                    lastField = parts[0]

        return fields
    finally:
        f.close()

def checkProposal(fn, fields):
    status = fields.get("Status")
    need_fields = REQUIRED_FIELDS + CONDITIONAL_FIELDS.get(status, [])
    for f in need_fields:
        if not fields.has_key(f):
            raise Error("%s has no %s field"%(fn, f))
    if fn != fields['Filename']:
        print `fn`, `fields['Filename']`
        raise Error("Mismatched Filename field in %s"%fn)
    if fields['Title'][-1] == '.':
        fields['Title'] = fields['Title'][:-1]

    status = fields['Status'] = status.upper()
    if status not in STATUSES:
        raise Error("I've never heard of status %s in %s"%(status,fn))
    if status in [ "SUPERSEDED", "DEAD" ]:
        for f in [ 'Implemented-In', 'Target' ]:
            if fields.has_key(f): del fields[f]

def readProposals():
    res = []
    for fn in os.listdir(DIR):
        m = FNAME_RE.match(fn)
        if not m: continue
        if not fn.endswith(".txt"):
            raise Error("%s doesn't end with .txt"%fn)
        num = m.group(1)
        fields = readProposal(fn)
        checkProposal(fn, fields)
        fields['num'] = num
        res.append(fields)
    return res

def writeIndexFile(proposals):
    proposals.sort(key=lambda f:f['num'])
    seenStatuses = set()
    for p in proposals:
        seenStatuses.add(p['Status'])

    out = open(TMPFILE, 'w')
    inf = open(OUTFILE, 'r')
    for line in inf:
        out.write(line)
        if line.startswith("====="): break
    inf.close()

    out.write("Proposals by number:\n\n")
    for prop in proposals:
        out.write("%(num)s  %(Title)s [%(Status)s]\n"%prop)
    out.write("\n\nProposals by status:\n\n")
    for s in STATUSES:
        if s not in seenStatuses: continue
        out.write(" %s:\n"%s)
        for prop in proposals:
            if s == prop['Status']:
                out.write("   %(num)s  %(Title)s"%prop)
                if prop.has_key('Target'):
                    out.write(" [for %(Target)s]"%prop)
                if prop.has_key('Implemented-In'):
                    out.write(" [in %(Implemented-In)s]"%prop)
                out.write("\n")
    out.close()
    os.rename(TMPFILE, OUTFILE)

try:
    os.unlink(TMPFILE)
except OSError:
    pass

writeIndexFile(readProposals())