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
|
#!/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)
|