diff options
Diffstat (limited to 'proposals.py')
-rwxr-xr-x | proposals.py | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/proposals.py b/proposals.py new file mode 100755 index 0000000..66c5b1b --- /dev/null +++ b/proposals.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +import html +import json +import sys + +import pywikiapi +import mwparserfromhell + +OSMWIKI_ENDPOINT = 'https://wiki.openstreetmap.org/w/api.php' + +osmwiki = pywikiapi.Site(OSMWIKI_ENDPOINT) + +# https://wiki.openstreetmap.org/w/index.php?title=Template:Proposal_page&action=edit + +CATEGORIES = ( + 'Category:Proposed features under way', + 'Category:Active features', + 'Category:Inactive features', +) + + +def find_proposals(): + for cat in CATEGORIES: + yield from osmwiki.query_pages( + generator='categorymembers', + gcmtitle=cat, + gcmlimit='max', + prop='revisions', + rvprop='content', + rvslots='main', + ) + + +def get_template_val(tpl, name): + param = tpl.get(name, None) + if param: + value = param.value.strip() + if value: + # turn empty strings into None + return value + + +proposals = [] + +for page in find_proposals(): + text = page['revisions'][0]['slots']['main']['content'] + doc = mwparserfromhell.parse(text) + templates = doc.filter_templates(matches=lambda t: t.name.matches('Proposal Page')) + + if not templates: + print('{{Proposal Page}} not found in ', page['title'], file=sys.stderr) + continue + + for comment in doc.ifilter_comments(): + # remove comments like <!-- Date the RFC email is sent to the Tagging list: YYYY-MM-DD --> + doc.remove(comment) + + tpl = templates[0] + page_title = page['title'] + + name = get_template_val(tpl, 'name') + if name: + name = html.unescape(name) + + status = get_template_val(tpl, 'status') + if status: + status = status.lower() + + draft_start = get_template_val(tpl, 'draftStartDate') + if draft_start in ('*', '-'): + draft_start = None + + rfc_start = get_template_val(tpl, 'rfcStartDate') + if rfc_start in ('*', '-'): + rfc_start = None + + vote_start = get_template_val(tpl, 'voteStartDate') + if vote_start in ('*', '-'): + vote_start = None + + definition = get_template_val(tpl, 'definition') + users = get_template_val(tpl, 'users') or get_template_val(tpl, 'user') + + proposals.append( + dict( + page_title=page_title, + name=name, + status=status, + definition=definition, + draft_start=draft_start, + rfc_start=rfc_start, + vote_start=vote_start, + authors=users, + ) + ) + +STATUSES = { + 'voting': 0, + 'proposed': 1, + 'draft': 2, + 'post-vote': 3, + 'approved': 4, + 'inactive': 5, + 'rejected': 6, + 'abandoned': 7, + 'canceled': 8, + 'obsoleted': 9, +} + + +def sort_key(proposal): + status = proposal['status'] + + if status in ('voting', 'approved', 'rejected'): + date = proposal['vote_start'] or '' + elif status == 'proposed': + date = proposal['rfc_start'] or '' + else: + date = proposal['draft_start'] or '' + + return (-STATUSES.get(proposal['status'], 10), date) + + +proposals.sort(key=sort_key, reverse=True) + +json.dump(proposals, sys.stdout) |