/
lp-election-helper
executable file
·109 lines (94 loc) · 4.27 KB
/
lp-election-helper
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
#!/usr/bin/python
from launchpadlib.launchpad import Launchpad
import argparse
import sys
import os
import subprocess
GPG_COMMAND = "gpg --keyserver=keyserver.ubuntu.com --batch --search-keys "
DEVNULL = open(os.devnull, 'wb') # Python3: subprocess.DEVNULL
VERSION = "lp-election-helper 1.0"
DESCRIPTION = "Harvests public email addresses from a launchpad group"
HELP_END = """
This script requires logging in to a Launchpad account with permission to view the email address
of members within the searched group, as Launchpad will hide emails from anonymous users.
"""
DEFAULT_BLACKLIST = ["package-import@ubuntu.com"]
# In the case of multiple email addresses, these domains are given preference, in order
PREFERRED_DOMAINS = ["kubuntu.org", "ubuntu.com", "canonical.com", "gmail.com"]
parser = argparse.ArgumentParser(prog='lp-election-helper', description=DESCRIPTION, epilog=HELP_END)
parser.add_argument('--version', action='version', version=VERSION)
parser.add_argument('--names', '-n', action='store_true',
help='output emails in "Full Name <email@foo.com>" format')
parser.add_argument('GROUP',
help='name of the Launchpad group to search for email addresses')
args = parser.parse_args()
# TODO: Add a cross-reference check for tech board (must be in both ubuntu-dev and ubuntumembers)
# Technically we allow people to be ubuntu devs who have individual package upload rights
# without obtaining full membership, however as of this writing no one falls under that.
search_group = args.GROUP
# In principle we could replace this manual blacklist with a generic launchpad "nonvoter" group and
# then exclude members of that group from the output here, but at the moment it's just one account
# TODO: support further tweaking of blacklist, such as excluding a whole launchpad group
blacklist = DEFAULT_BLACKLIST
def find_preferred_domain(emails):
if len(emails) > 1:
for preferred_domain in PREFERRED_DOMAINS:
for possible_email in emails:
if possible_email.endswith("@" + preferred_domain):
return possible_email
return emails[0]
def extract_mails_from_key(fingerprint):
command = GPG_COMMAND + "0x" + fingerprint + " | tee"
gpg_output = subprocess.check_output(command, shell=True, stderr=DEVNULL)
possible_emails = [line for line in gpg_output.split('<') if '>' in line]
emails = [line.split('>')[0] for line in possible_emails]
for email in emails:
yield email
# Python3: replace last 3 lines with: yield from (line.split('>')[0] for line in possible_emails)
def extract_mails_from_keys(gpg_keys):
emails = []
for key in gpg_keys:
for email in extract_mails_from_key(key.fingerprint):
emails.append(email)
for email in emails:
yield email
# Python3: replace last 4 lines with: yield from extract_mails_from_key(key.fingerprint)
def get_email(person):
try:
email = person.preferred_email_address.email
return email
except ValueError:
emails = [p.email for p in person.confirmed_email_addresses] or \
[email for email in extract_mails_from_keys(person.gpg_keys)]
if emails:
return find_preferred_domain(emails)
return "-"
def main():
launchpad = Launchpad.login_with('mails', 'production', os.path.expanduser("~/.launchpadlib/cache/"))
members = [member for member in launchpad.people[search_group].participants if not member.is_team]
missed_accounts = []
print "#### Members with verified public email addresses ####"
print
for member in members:
email = get_email(member)
if email in blacklist:
continue
if email is not "-":
if args.names:
print "%s <%s>" % (member.display_name, email)
else:
print email
else:
missed_account = "%s (%s)" % (member.display_name, member.name)
missed_accounts.append(missed_account)
print
print "#### Members with no public email address or GPG key ####"
print
for missed_account in missed_accounts:
print missed_account
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print >> sys.stderr, "Aborted."
sys.exit(1)