9
9
import sys
10
10
import requests
11
11
import getpass
12
+ import time
12
13
13
- # With authentication: up to 5000 requests per hour.
14
14
print ("user:" , file = sys .stderr )
15
15
user = input ()
16
16
passwd = getpass .getpass ("Password or access token:\n " )
20
20
LOGO_URL = 'https://avatars2.githubusercontent.com/u/365630?v=4'
21
21
22
22
23
+ def get (url ):
24
+ for sleep_time in [10 , 30 , 0 ]:
25
+ reply = requests .get (url , auth = auth )
26
+ api_limit = ("message" in reply .json ()
27
+ and "API rate limit exceeded" in reply .json ()["message" ])
28
+ if not api_limit :
29
+ break
30
+ print ("API rate limit exceeded, waiting.." )
31
+ time .sleep (sleep_time )
32
+
33
+ reply .raise_for_status ()
34
+ return reply
35
+
36
+
23
37
def group_iterable (iterable , size ):
24
38
"""Group iterable into lines"""
25
39
group = []
@@ -34,73 +48,121 @@ def group_iterable(iterable, size):
34
48
35
49
def get_contributors ():
36
50
"""Get the list of contributor profiles. Require admin rights."""
37
- # get members of scikit-learn teams on GitHub
38
- members = []
51
+ # get members of scikit-learn core-dev on GitHub
52
+ core_devs = []
39
53
team = 11523
40
54
for page in [1 , 2 ]: # 30 per page
41
- reply = requests .get (
42
- "https://api.github.com/teams/%d/members?page=%d"
43
- % (team , page ), auth = auth )
44
- reply .raise_for_status ()
55
+ reply = get ("https://api.github.com/teams/%d/members?page=%d" %
56
+ (team , page ))
57
+ core_devs .extend (reply .json ())
58
+
59
+ # get members of scikit-learn on GitHub
60
+ members = []
61
+ for page in [1 , 2 ]: # 30 per page
62
+ reply = get (
63
+ "https://api.github.com/orgs/scikit-learn/members?page=%d" %
64
+ (page , ))
45
65
members .extend (reply .json ())
46
66
47
67
# keep only the logins
48
- logins = [c ['login' ] for c in members ]
49
- # remove duplicate
50
- logins = set (logins )
68
+ core_devs = [c ['login' ] for c in core_devs ]
69
+ members = [c ['login' ] for c in members ]
70
+
71
+ # add missing contributors with GitHub accounts
72
+ members .extend (['dubourg' , 'mbrucher' , 'thouis' , 'jarrodmillman' ])
73
+ # add missing contributors without GitHub accounts
74
+ members .extend (['Angel Soler Gollonet' ])
75
+ # remove CI bots
76
+ members .remove ('sklearn-ci' )
77
+ members .remove ('sklearn-lgtm' )
78
+ members .remove ('sklearn-wheels' )
79
+
80
+ # remove duplicate, and get the difference of the two sets
81
+ core_devs = set (core_devs )
82
+ members = set (members )
83
+ emeritus = members .difference (core_devs )
51
84
52
85
# get profiles from GitHub
53
- profiles = [get_profile (login ) for login in logins ]
86
+ core_devs = [get_profile (login ) for login in core_devs ]
87
+ emeritus = [get_profile (login ) for login in emeritus ]
88
+
54
89
# sort by last name
55
- profiles = sorted (profiles , key = key )
90
+ core_devs = sorted (core_devs , key = key )
91
+ emeritus = sorted (emeritus , key = key )
56
92
57
- return profiles
93
+ return core_devs , emeritus
58
94
59
95
60
96
def get_profile (login ):
61
97
"""Get the GitHub profile from login"""
62
- profile = requests . get ( "https://api.github.com/users/ %s" % login ,
63
- auth = auth ). json ()
64
- if 'name' not in profile :
65
- # default profile if the login does not exist
98
+ print ( "get profile for %s" % ( login , ))
99
+ try :
100
+ profile = get ( "https://api.github.com/users/%s" % login ). json ()
101
+ except requests . exceptions . HTTPError :
66
102
return dict (name = login , avatar_url = LOGO_URL , html_url = "" )
67
- else :
68
- if profile ["name" ] is None :
69
- profile ["name" ] = profile ["login" ]
70
103
71
- # fix missing names
72
- missing_names = {'bthirion' : 'Bertrand Thirion' ,
73
- 'Duchesnay' : 'Edouard Duchesnay' ,
74
- 'Lars' : 'Lars Buitinck' ,
75
- 'MechCoder' : 'Manoj Kumar' }
76
- if profile ["name" ] in missing_names :
77
- profile ["name" ] = missing_names [profile ["name" ]]
78
- return profile
104
+ if profile ["name" ] is None :
105
+ profile ["name" ] = profile ["login" ]
106
+
107
+ # fix missing names
108
+ missing_names = {
109
+ 'bthirion' : 'Bertrand Thirion' ,
110
+ 'dubourg' : 'Vincent Dubourg' ,
111
+ 'Duchesnay' : 'Edouard Duchesnay' ,
112
+ 'Lars' : 'Lars Buitinck' ,
113
+ 'MechCoder' : 'Manoj Kumar' ,
114
+ 'jeremiedbb' : 'Jérémie Du Boisberranger' ,
115
+ }
116
+ if profile ["name" ] in missing_names :
117
+ profile ["name" ] = missing_names [profile ["name" ]]
118
+
119
+ return profile
79
120
80
121
81
122
def key (profile ):
82
123
"""Get the last name in lower case"""
83
124
return profile ["name" ].split (' ' )[- 1 ].lower ()
84
125
85
126
86
- contributors = get_contributors ()
87
-
88
- print (".. raw :: html\n " )
89
- print (" <!-- Generated by generate_authors_table.py -->" )
90
- print (" <table>" )
91
- print (" <col style='width:%d%%' span='%d'>"
92
- % (int (100 / ROW_SIZE ), ROW_SIZE ))
93
- print (" <style>" )
94
- print (" img.avatar {border-radius: 10px;}" )
95
- print (" td {vertical-align: top;}" )
96
- print (" </style>" )
97
- for row in group_iterable (contributors , size = ROW_SIZE ):
98
- print (" <tr>" )
99
- for contributor in row :
100
- print (" <td>" )
101
- print (" <a href='%s'><img src='%s' class='avatar' /></a> <br />"
102
- % (contributor ["html_url" ], contributor ["avatar_url" ]))
103
- print (" <p>%s</p>" % contributor ["name" ])
104
- print (" </td>" )
105
- print (" </tr>" )
106
- print (" </table>" )
127
+ def generate_table (contributors ):
128
+ lines = [
129
+ (".. raw :: html\n " ),
130
+ (" <!-- Generated by generate_authors_table.py -->" ),
131
+ (" <table>" ),
132
+ (" <col style='width:%d%%' span='%d'>" %
133
+ (int (100 / ROW_SIZE ), ROW_SIZE )),
134
+ (" <style>" ),
135
+ (" img.avatar {border-radius: 10px;}" ),
136
+ (" td {vertical-align: top;}" ),
137
+ (" </style>" ),
138
+ ]
139
+ for row in group_iterable (contributors , size = ROW_SIZE ):
140
+ lines .append (" <tr>" )
141
+ for contributor in row :
142
+ lines .append (" <td>" )
143
+ lines .append (
144
+ " <a href='%s'><img src='%s' class='avatar' /></a> <br />" %
145
+ (contributor ["html_url" ], contributor ["avatar_url" ]))
146
+ lines .append (" <p>%s</p>" % (contributor ["name" ], ))
147
+ lines .append (" </td>" )
148
+ lines .append (" </tr>" )
149
+ lines .append (" </table>" )
150
+ return '\n ' .join (lines )
151
+
152
+
153
+ def generate_list (contributors ):
154
+ lines = []
155
+ for contributor in contributors :
156
+ lines .append ("- %s" % (contributor ["name" ], ))
157
+ return '\n ' .join (lines )
158
+
159
+
160
+ if __name__ == "__main__" :
161
+
162
+ core_devs , emeritus = get_contributors ()
163
+
164
+ with open ("../doc/authors.rst" , "w+" ) as rst_file :
165
+ rst_file .write (generate_table (core_devs ))
166
+
167
+ with open ("../doc/authors_emeritus.rst" , "w+" ) as rst_file :
168
+ rst_file .write (generate_list (emeritus ))
0 commit comments