Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| #!/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 = ["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 ####" | |
| 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 "#### Members with no public email address or GPG key ####" | |
| for missed_account in missed_accounts: | |
| print missed_account | |
| if __name__ == '__main__': | |
| try: | |
| main() | |
| except KeyboardInterrupt: | |
| print >> sys.stderr, "Aborted." | |
| sys.exit(1) | |