summaryrefslogtreecommitdiff
path: root/proposals.py
blob: 66c5b1b0315e71fd9785779926dc7ddf8a7cdcee (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
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)