Source code for repo_stats.user_stats

import textwrap
from datetime import UTC, datetime

from PIL import Image, ImageDraw, ImageFont


[docs] class StatsImage: def __init__(self, template_image, font) -> None: """ Class for updating a template image (e.g. to be displayed in a GitHub README) with repository and citation statistics. Arguments --------- template_image : str Template image to be updated font : str Font file (.tff) to be used """ if "dark" in template_image: self.theme = "dark" self.text_color = "#ffffff" elif "light" in template_image: self.theme = "light" self.text_color = "#000000" else: self.theme = "transparent" self.text_color = "#999999" self.img = Image.open(template_image) self.draw = ImageDraw.Draw(self.img) self.font = font self.font_size = 54 self.font_instance = ImageFont.truetype(font, self.font_size)
[docs] def draw_text(self, coords, text, text_color=None, font=None, **kwargs): """ Convenience wrapper for 'PIL.ImageDraw.Draw'. Arguments --------- coords : tuple of int (x,y) coordinates of text location text : str Text to be drawn text_color : str, default=None Text color font : 'PIL.ImageFont' instance, default=None Text font """ if text_color is None: text_color = self.text_color if font is None: font = self.font_instance self.draw.text(coords, str(text), fill=text_color, font=font, **kwargs)
[docs] def update_image(self, stats, repo_name, cache_dir): """ Update the provided template image with text summarizing repository and citation statistics. Arguments --------- stats : dict A dictionary entry for each issue or pull request in the history (see `git_metrics.get_issues_prs`) repo_name : str Name of repository on GitHub (for drawn text) cache_dir : str Name of directory in which to cache updated image Returns ------- self.img : 'PIL.Image' instance The provided template image updated with text """ self.draw_text( (70, 404), f"{stats['n_recent_authors']} total contributors in last {stats['age_recent_commit']} days", ) self.draw_text( (70, 30), f"{len(stats['new_authors'])} new contributors in last {stats['age_recent_commit']} days:", ) # case-insensitive sort text_authors = sorted(stats["new_authors"], key=str.lower) # bound text block to fit in available space. # see Image.getbbox - https://pillow.readthedocs.io/en/stable/reference/Image.html max_bbox = (70, 113, 1100, 320) out_of_bounds = [True] fs = self.font_size * 1 while True in out_of_bounds: text_authors_wrap = "\n".join(textwrap.wrap(", ".join(text_authors))) text_bbox = self.draw.textbbox( (70, 100), text_authors_wrap, font=ImageFont.truetype(self.font, fs), ) out_of_bounds = [True for i, x in enumerate(text_bbox) if x > max_bbox[i]] fs -= 1 self.draw_text( (70, 100), text_authors_wrap, font=ImageFont.truetype(self.font, fs), ) self.draw_text( (1258, 51), f"last {stats['issues']['age_recent']} days: {stats['issues']['recent_close']} issues closed, {stats['issues']['recent_open']} opened\n{stats['pullRequests']['recent_close']} PRs closed, {stats['pullRequests']['recent_open']} opened", align="right", ) self.draw_text( (1390, 285), f"papers citing {repo_name}: {stats['aggregate']['cite_month']} last month\n{stats['aggregate']['cite_year']} this year\n{stats['aggregate']['cite_all']} all-time", align="right", ) now = datetime.now(UTC).strftime("%B %d, %Y") self.draw_text( (1210, 465), f"Generated on {now}", font=ImageFont.truetype(self.font, 34), ) self.img.save(f"{cache_dir}/{repo_name}_user_stats_{self.theme}.png") return self.img