Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 110 lines (94 sloc) 4.27 KB
#!/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)