Skip to content

Commit b5f1602

Browse files
committed
Add another xmlrpc example script and update readme.
Also added basic description of Docker files in Docker subdirectory (to be added).
1 parent ede93f3 commit b5f1602

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

scripts/README.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ spam-remover
3131
Remove file attachment spam from a tracker. (Warning destructive,
3232
read script well.)
3333

34+
stats.xmlrpc.py
35+
Script using the xmlrpc interface to retrieve info. Generates report
36+
on what values are used by the various issues on bugs.python.org.
37+
3438
weekly-report
3539
Generate a simple report outlining the activity in one tracker for the
3640
most recent week.
@@ -56,3 +60,18 @@ systemd.gunicorn
5660
contributors.py
5761
Analyzes Mercurial log, filters and compiles list of committers with years
5862
of contribution. Can be useful for updating COPYING.txt
63+
64+
----
65+
66+
Docker
67+
Directory for docker setup. More info on how to use it is in
68+
doc/installation.txt.
69+
70+
Docker/Dockerfile - Create roundup docker.
71+
72+
Docker/requirements.txt - Python requirements built into docker.
73+
74+
Docker/roundup-start - Startup script for roundup in docker.
75+
76+
Docker/docker-compose.yml - Manage two docker containers for roundup
77+
and mysql.

scripts/stats.xmlrpc.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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+

0 commit comments

Comments
 (0)