aboutsummaryrefslogtreecommitdiff
path: root/proposals/reindex.py
diff options
context:
space:
mode:
Diffstat (limited to 'proposals/reindex.py')
-rwxr-xr-xproposals/reindex.py200
1 files changed, 0 insertions, 200 deletions
diff --git a/proposals/reindex.py b/proposals/reindex.py
deleted file mode 100755
index 72b1234..0000000
--- a/proposals/reindex.py
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-if sys.version_info[0] < 3:
- print("No support for Python 2.")
- sys.exit(1)
-
-import codecs, re, os
-class Error(Exception): pass
-
-STATUSES = """DRAFT NEEDS-REVISION NEEDS-RESEARCH OPEN ACCEPTED META FINISHED
- CLOSED SUPERSEDED DEAD REJECTED OBSOLETE RESERVE INFORMATIONAL""".split()
-REQUIRED_FIELDS = [ "Filename", "Status", "Title"]
-CONDITIONAL_FIELDS = { "OPEN" : [ "Target", "Ticket" ],
- "ACCEPTED" : [ "Target", "Ticket" ],
- "CLOSED" : [ "Implemented-In", "Ticket" ],
- "FINISHED" : [ "Implemented-In", "Ticket" ] }
-FNAME_RE = re.compile(r'^(\d\d\d)-.*[^\~]$')
-DIR = "."
-OUTFILE_TXT = "000-index.txt"
-TMPFILE_TXT = OUTFILE_TXT+".tmp"
-
-TEMPFILES = [TMPFILE_TXT]
-
-def unlink_if_present(fname):
- try:
- os.unlink(fname)
- except OSError:
- pass
-
-def indexed(seq):
- n = 0
- for i in seq:
- yield n, i
- n += 1
-
-def readProposal(fn):
- fields = { }
- f = codecs.open(fn, 'r', encoding='utf-8')
- 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())
- elif line == "```":
- pass
- else:
- parts = line.split(":", 1)
- if len(parts) != 2:
- raise Error("%s:%s: Neither field, continuation, nor ```."%
- (fn,lineno))
- else:
- fields[parts[0]] = parts[1].strip()
- lastField = parts[0]
-
- return fields
- finally:
- f.close()
-
-def getProposalNumber(fn):
- """Get the proposal's assigned number from its filename `fn`."""
- parts = fn.split('-', 1)
-
- assert len(parts) == 2, \
- "Filename must have a proposal number and title separated by a '-'"
-
- return int(parts[0])
-
-def checkProposal(fn, fields):
- status = fields.get("Status")
- need_fields = REQUIRED_FIELDS + CONDITIONAL_FIELDS.get(status, [])
-
- number = getProposalNumber(fn)
- # Since prop#288 was the newest when we began requiring the 'Ticket:'
- # field, we don't require the field for it or any older proposal.
- # (Although you're encouraged to add it to your proposal, and add it for
- # older proposals where you know the correct ticket, as it greatly helps
- # newcomers find more information on the implementation.)
- if number <= 288:
- if "Ticket" in need_fields:
- need_fields.remove("Ticket")
-
- for f in need_fields:
- if f not in fields:
- raise Error("%s has no %s field"%(fn, f))
- if 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 f in fields: del fields[f]
-
-def readProposals():
- res = []
- for fn in os.listdir(DIR):
- m = FNAME_RE.match(fn)
- if not m: continue
- if fn.endswith(".tmp"):
- continue
- if not (fn.endswith(".txt") or fn.endswith(".md")):
- raise Error("%s doesn't end with .txt or .md"%fn)
- num = m.group(1)
- fields = readProposal(fn)
- checkProposal(fn, fields)
- fields['num'] = num
- res.append(fields)
- return res
-
-def writeTextIndexFile(proposals):
- proposals.sort(key=lambda f:f['num'])
- seenStatuses = set()
- for p in proposals:
- seenStatuses.add(p['Status'])
-
- out = open(TMPFILE_TXT, 'w')
- inf = open(OUTFILE_TXT, '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 "Target" in prop:
- out.write(" [for %(Target)s]"%prop)
- if "Implemented-In" in prop:
- out.write(" [in %(Implemented-In)s]"%prop)
- out.write("\n")
- out.close()
- os.rename(TMPFILE_TXT, OUTFILE_TXT)
-
-def formatMarkdownEntry(prop, withStatus=False):
- if withStatus:
- fmt = "* [`{Filename}`](/proposals/{Filename}): {Title} [{Status}]\n"
- else:
- fmt = "* [`{Filename}`](/proposals/{Filename}): {Title}\n"
- return fmt.format(**prop)
-
-def writeMarkdownFile(prefix, format_inputs):
- template = prefix+"_template.md"
- output = prefix+".md"
- t = open(template).read()
- content = t.format(**format_inputs)
- with open(output, 'w') as f:
- f.write(content)
-
-def writeMarkdownIndexFiles(proposals):
- markdown_files = [ "README", "BY_INDEX" ]
- format_inputs = {}
-
- format_inputs['warning'] = "<!-- DO NOT EDIT THIS FILE -->"
-
- entries = []
- for prop in proposals:
- entries.append(formatMarkdownEntry(prop, withStatus=True))
- format_inputs["BY_INDEX"] = "".join(entries)
-
- for s in STATUSES:
- entries = []
- for prop in proposals:
- if s == prop['Status']:
- entries.append(formatMarkdownEntry(prop))
- if entries:
- format_inputs[s] = "".join(entries)
- else:
- format_inputs[s] = "(There are no proposals in this category)\n"
-
- entries = []
- for prop in proposals:
- if prop['Status'] in ('DEAD', 'REJECTED', 'OBSOLETE'):
- entries.append(formatMarkdownEntry(prop, withStatus=True))
- format_inputs['DEAD_REJECTED_OBSOLETE'] = "".join(entries)
-
- for prefix in markdown_files:
- writeMarkdownFile(prefix, format_inputs)
-
-if __name__ == '__main__':
- proposals = readProposals()
- try:
- writeTextIndexFile(proposals)
- writeMarkdownIndexFiles(proposals)
- finally:
- for tempfile in TEMPFILES:
- unlink_if_present(tempfile)