comparison scripts/stats.xmlrpc.py @ 6553:75da037d1c54

Add another xmlrpc example script and update readme. Also added basic description of Docker files in Docker subdirectory (to be added).
author John Rouillard <rouilj@ieee.org>
date Sat, 11 Dec 2021 21:26:46 -0500
parents
children
comparison
equal deleted inserted replaced
6552:e1146767b42e 6553:75da037d1c54
1 """Count how many issues use each bpo field and print a report."""
2 """ sample output: https://github.com/psf/gh-migration/issues/5#issuecomment-935697646"""
3
4 import xmlrpc.client
5
6 from collections import defaultdict
7
8 class SpecialTransport(xmlrpc.client.SafeTransport):
9 def send_content(self, connection, request_body):
10 connection.putheader("Referer", "https://bugs.python.org/")
11 connection.putheader("Origin", "https://bugs.python.org")
12 connection.putheader("X-Requested-With", "XMLHttpRequest")
13 xmlrpc.client.SafeTransport.send_content(self, connection, request_body)
14
15 # connect to bpo
16 roundup = xmlrpc.client.ServerProxy('https://bugs.python.org/xmlrpc',
17 transport=SpecialTransport(),
18 allow_none=True)
19
20 # map bpo classes -> propname
21 # the class is the name of the class (e.g. issue_type, keyword --
22 # also used in e.g. in https://bugs.python.org/keyword)
23 # the propname is the name used as attribute on the issue class
24 # (e.g. issue.type, issue.keywords)
25 classes = {
26 # 'status': 'status', # skip this
27 'issue_type': 'type',
28 'stage': 'stage',
29 'component': 'components',
30 'version': 'versions',
31 'resolution': 'resolution',
32 'priority': 'priority',
33 'keyword': 'keywords',
34 }
35
36 # find the id for the 'open' status
37 open_id = roundup.lookup('status', 'open')
38
39 print(f'* Counting total issues...')
40 total_issues_num = len(roundup.filter('issue', None, {}))
41
42 print(f'* Counting open issues...')
43 # use this list to filter only the open issues
44 open_issues = roundup.filter('issue', None, {'status': open_id})
45 open_issues_num = len(open_issues)
46
47 # save the totals in a dict with this structure:
48 # totals[propname][open/all][num/perc][name]
49 # where propname is e.g. 'keyword' and name is e.g. 'easy'
50 totals = defaultdict(lambda: {'all': {'perc': {}, 'num': {}},
51 'open': {'perc': {}, 'num': {}}})
52 for cls, propname in classes.items():
53 print(f'* Counting <{cls}>...')
54 # get the list of ids/names for the given class (e.g. 'easy' is 6)
55 ids = roundup.list(cls, 'id')
56 names = roundup.list(cls, 'name')
57 for id, name in zip(ids, names):
58 # filter and count on *all* issues with the given propname
59 tot_all = len(roundup.filter('issue', None, {propname: id}))
60 totals[propname]['all']['num'][name] = tot_all
61 totals[propname]['all']['perc'][name] = tot_all / total_issues_num
62 # filter and count on *open* issues with the given propname
63 tot_open = len(roundup.filter('issue', open_issues, {propname: id}))
64 totals[propname]['open']['num'][name] = tot_open
65 totals[propname]['open']['perc'][name] = tot_open / open_issues_num
66
67
68 print(f'Issues (open/all): {open_issues_num}/{total_issues_num}')
69
70 # print a list of markdown tables for each bpo class name
71 for propname in classes.values():
72 print(f'### {propname}')
73 print('| bpo field | open | all |')
74 print('| :--- | ---: | ---: |')
75 # pick the dict for the given propname (e.g. keywords)
76 proptots = totals[propname]
77 names = proptots['open']['num']
78 # sort the names (e.g. 'easy') in reverse order
79 # based on the number of open issues
80 for name in sorted(names, key=names.get, reverse=True):
81 # get and print num/perc for all/open issues
82 issues_all = proptots['all']['num'][name]
83 issues_open = proptots['open']['num'][name]
84 perc_all = proptots['all']['perc'][name]
85 perc_open = proptots['open']['perc'][name]
86 print(f'| {name:20} | {issues_open:>5} ({perc_open:5.1%}) |'
87 f' {issues_all:>5} ({perc_all:5.1%}) |')
88 # calc and print num/perc for all/open issues
89 tot_issues_all = sum(proptots['all']['num'].values())
90 tot_issues_open = sum(proptots['open']['num'].values())
91 tot_perc_all = sum(proptots['all']['perc'].values())
92 tot_perc_open = sum(proptots['open']['perc'].values())
93 print(f'| **Total** | {tot_issues_open:>5} ({tot_perc_open:5.1%}) |'
94 f' {tot_issues_all:>5} ({tot_perc_all:5.1%}) |')
95

Roundup Issue Tracker: http://roundup-tracker.org/