#!/usr/bin/env python3 # Copyright (c) 2009 Giampaolo Rodola'. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Print PYPI statistics in MarkDown format. Useful sites: * https://pepy.tech/project/psutil * https://pypistats.org/packages/psutil * https://hugovk.github.io/top-pypi-packages/. """ import json import os import shlex import subprocess import sys import pypinfo # noqa: F401 from psutil._common import memoize AUTH_FILE = os.path.expanduser("~/.pypinfo.json") PKGNAME = 'psutil' DAYS = 30 LIMIT = 100 GITHUB_SCRIPT_URL = ( "https://github.com/giampaolo/psutil/blob/master/" "scripts/internal/pypistats.py" ) LAST_UPDATE = None bytes_billed = 0 # --- get @memoize def sh(cmd): assert os.path.exists(AUTH_FILE) env = os.environ.copy() env['GOOGLE_APPLICATION_CREDENTIALS'] = AUTH_FILE p = subprocess.Popen( shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=env, ) stdout, stderr = p.communicate() if p.returncode != 0: raise RuntimeError(stderr) assert not stderr, stderr return stdout.strip() @memoize def query(cmd): global bytes_billed ret = json.loads(sh(cmd)) bytes_billed += ret['query']['bytes_billed'] return ret def top_packages(): global LAST_UPDATE ret = query( f"pypinfo --all --json --days {DAYS} --limit {LIMIT} '' project" ) LAST_UPDATE = ret['last_update'] return [(x['project'], x['download_count']) for x in ret['rows']] def ranking(): data = top_packages() i = 1 for name, downloads in data: if name == PKGNAME: return i i += 1 raise ValueError(f"can't find {PKGNAME}") def downloads(): data = top_packages() for name, downloads in data: if name == PKGNAME: return downloads raise ValueError(f"can't find {PKGNAME}") def downloads_pyver(): return query(f"pypinfo --json --days {DAYS} {PKGNAME} pyversion") def downloads_by_country(): return query(f"pypinfo --json --days {DAYS} {PKGNAME} country") def downloads_by_system(): return query(f"pypinfo --json --days {DAYS} {PKGNAME} system") def downloads_by_distro(): return query(f"pypinfo --json --days {DAYS} {PKGNAME} distro") # --- print templ = "| {:<30} | {:>15} |" def print_row(left, right): if isinstance(right, int): right = f"{right:,}" print(templ.format(left, right)) def print_header(left, right="Downloads"): print_row(left, right) s = templ.format("-" * 30, "-" * 15) print("|:" + s[2:-2] + ":|") def print_markdown_table(title, left, rows): pleft = left.replace('_', ' ').capitalize() print("### " + title) print() print_header(pleft) for row in rows: lval = row[left] print_row(lval, row['download_count']) print() def main(): downs = downloads() print("# Download stats") print() s = f"psutil download statistics of the last {DAYS} days (last update " s += f"*{LAST_UPDATE}*).\n" s += f"Generated via [pypistats.py]({GITHUB_SCRIPT_URL}) script.\n" print(s) data = [ {'what': 'Per month', 'download_count': downs}, {'what': 'Per day', 'download_count': int(downs / 30)}, {'what': 'PYPI ranking', 'download_count': ranking()}, ] print_markdown_table('Overview', 'what', data) print_markdown_table( 'Operating systems', 'system_name', downloads_by_system()['rows'] ) print_markdown_table( 'Distros', 'distro_name', downloads_by_distro()['rows'] ) print_markdown_table( 'Python versions', 'python_version', downloads_pyver()['rows'] ) print_markdown_table( 'Countries', 'country', downloads_by_country()['rows'] ) if __name__ == '__main__': try: main() finally: print(f"bytes billed: {bytes_billed}", file=sys.stderr)