Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 95 lines (80 sloc) 3.95 KB
import sys
import os
import argparse
from launchpadlib.launchpad import Launchpad
from lazr.restfulclient.errors import ServerError
VERSION = "ppa-stats 1.0"
DESCRIPTION = "Prints download statistics for binary packages in a Launchpad PPA."
HELP_END = """
The -p, -s, and -a arguments can all be given multiple times, or as a comma-seperated
Note that Launchpad is unable to provide individual release information for packages
which are binary copied from one release to another. In such a case, the given number
will represent the sum of downloads across all releases sharing that binary package.
# TODO: implement an argument for specifying days, via
# getDailyDownloadTotals(start_date='2011-09-22', end_date='2011-09-23')
parser = argparse.ArgumentParser(prog='ppa-stats', description=DESCRIPTION, epilog=HELP_END)
parser.add_argument('-p', '--package',
help='specify a package name (default: any)',
parser.add_argument('-s', '--series',
help='specify a series name (default: any)',
parser.add_argument('-a', '--arch',
help='specify an architecture (default: any)',
parser.add_argument('-l', '--login',
help='login to launchpad non-anonymously (required for private PPAs)',
parser.add_argument('--version', action='version', version=VERSION)
help='full name of the Launchpad PPA including the owning team or user and \
a slash, as in "PPA-Owner/PPA-Name"')
args = parser.parse_args()
ppa_owner, ppa_name = args.PPA.split('/')
except ValueError:
parser.error("Malformed PPA name '%s': Try ppa-owner/ppa-name" % args.PPA)
# Creates a list of strings into a list, eg ['foo', 'bar,', 'x,y,z'] -> ['foo','bar','x','y','z']
def list_from_comma_items(items):
output = []
for item in items:
return output
# We use sets to avoid duplication, especially the unexpected -p wine -p wine1.6 giving 2x wine1.6
if args.package is not None: package_whitelist = set(list_from_comma_items(args.package))
if args.arch is not None: arch_whitelist = set(list_from_comma_items(args.arch))
if args.series is not None: series_whitelist = set(list_from_comma_items(args.series))
# Login to Launchpad
cache_path = os.path.expanduser("~/.launchpadlib/cache/")
if args.login:
# note launchpadlib prints output about logging in here to standard out rather than stderr
lp = Launchpad.login_with('ppastats', 'production', cache_path)
lp = Launchpad.login_anonymously('ppastats', 'production', cache_path)
ppa = lp.people[ppa_owner].getPPAByName(name=ppa_name)
# Build the list of binaries to query
if args.package is None:
binaries = ppa.getPublishedBinaries(status='Published')
all_binaries = []
for package in package_whitelist:
all_binaries.extend(ppa.getPublishedBinaries(status='Published', binary_name=package))
# LP will return more than we ask above, eg wine1.7-amd64 when you asked for wine1.7
binaries = [x for x in all_binaries if x.binary_package_name in package_whitelist]
# TODO: consider making some attempt to order them, eg in arg order for individual packages
for binary in binaries:
splitted = binary.distro_arch_series_link.split("/");
series = splitted[-2]
arch = splitted[-1]
if args.series and series not in series_whitelist: continue
if args.arch and arch not in arch_whitelist: continue
downloadCount = binary.getDownloadCount()
except ServerError:
sys.stderr.write("Server Error: If this was a large PPA with many packages, try \
restricting your query with -p, -s, or -a")
print ("%s %s %s %d") % (binary.binary_package_name, series, arch, downloadCount)