From 2406b2541dcb9f4ca72bcf3c3bd224903dca04f0 Mon Sep 17 00:00:00 2001 From: shaunak01 Date: Sat, 24 May 2025 21:44:14 +0000 Subject: [PATCH 1/8] Fix --- .../notebooks/github_utils_test.ipynb | 679 ++++++++++++++++++ 1 file changed, 679 insertions(+) create mode 100644 tutorial_github_causify_style/notebooks/github_utils_test.ipynb diff --git a/tutorial_github_causify_style/notebooks/github_utils_test.ipynb b/tutorial_github_causify_style/notebooks/github_utils_test.ipynb new file mode 100644 index 0000000000..30e95897b0 --- /dev/null +++ b/tutorial_github_causify_style/notebooks/github_utils_test.ipynb @@ -0,0 +1,679 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "CONTENTS:\n", + "- [Github API to understand user Contribution](#github-api-to-understand-user-contribution)\n", + " - [These numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.](#these-numbers-come-straight-from-the-upstream-repo-via-the-rest-api,-so-they-only-include-commits-and-prs-where-you\u2019re-the-author-or-the-committer-on-that-repo.-they-**do-not**-pick-up-any-work-you-did-in-a-fork-(or-the-individual-commits-squashed-into-a-single-merge),-which-is-why-they\u2019ll-always-undercount-what-github-insights-shows-for-your-overall-contributions.)\n", + " - [Set your Github PAT](#set-your-github-pat)\n", + " - [Pre-feth all the data you need in cache](#pre-feth-all-the-data-you-need-in-cache)\n", + " - [Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period](#query-extraction-takes-time,-so-prefetch-all-data-in-cache-for-all-the-users,-repos-and-time-frames-you-need.-once-in-cache-there-are-several-utility-functions-to-help-understand-the-user-contribution.-following-is-the-data-we-will-fetch-for-users-in-multiple-repos-for-the-given-period)\n", + " - [Combine the data for statistics and visualizations](#combine-the-data-for-statistics-and-visualizations)\n", + " - [Compare users on a repo based on `commits`, `prs`, `additions` and `deletions`](#compare-users-on-a-repo-based-on-`commits`,-`prs`,-`additions`-and-`deletions`)\n", + " - [See stats of a user on multiple repos based on `commits`, `prs`, `additions` and `deletions`](#see-stats-of-a-user-on-multiple-repos-based-on-`commits`,-`prs`,-`additions`-and-`deletions`)\n", + " - [There are many more helper funcs to see and compare statistics. Look at github_utils for more info -> `tutorial_github_causify_style/github_utils.py`](#there-are-many-more-helper-funcs-to-see-and-compare-statistics.-look-at-github_utils-for-more-info-->-`tutorial_github_causify_style/github_utils.py`)" + ] + }, + { + "cell_type": "markdown", + "id": "8bdfbc31-a6d6-431e-b0ed-bdc69b8eec25", + "metadata": {}, + "source": [ + "\n", + "# Github API to understand user Contribution" + ] + }, + { + "cell_type": "markdown", + "id": "923ef379-8424-46df-9b60-29d35a63a331", + "metadata": {}, + "source": [ + "\n", + "### These numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "442cd592-3137-4d73-a113-655bf8dfd3fe", + "metadata": {}, + "outputs": [], + "source": [ + "!sudo /bin/bash -c \"(source /venv/bin/activate; pip install --quiet jupyterlab-vim PyGithub)\"\n", + "!jupyter labextension enable" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "268ddc35-9bb4-4e0a-b7f4-a8409baf9904", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "import os\n", + "import datetime\n", + "import time\n", + "import importlib \n", + "\n", + "import github_utils\n", + "import helpers.hcache_simple as hcache\n", + "import helpers.hcache_simple as hcacsimp\n", + "from github import Github\n", + "\n", + "# Enable logging.\n", + "logging.basicConfig(level=logging.INFO)\n", + "_LOG = logging.getLogger(__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9c25ee1d-620b-485e-b98c-769c7fff8ab4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "importlib.reload(github_utils)" + ] + }, + { + "cell_type": "markdown", + "id": "6afd498b-8453-42e1-852c-ac093f8e0bfd", + "metadata": {}, + "source": [ + "\n", + "## Set your Github PAT" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3220998c-1261-418f-859b-b20bb9a6cb61", + "metadata": {}, + "outputs": [], + "source": [ + "# Set your GitHub access token here.\n", + "os.environ[\"GITHUB_ACCESS_TOKEN\"] = \"YOUR_GITHUB_PAT\"" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "03983a64-78a2-49c3-9163-815cf0ef3a77", + "metadata": {}, + "outputs": [], + "source": [ + "access_token = os.getenv(\"GITHUB_ACCESS_TOKEN\")\n", + "if not access_token:\n", + " _LOG.error(\"GITHUB_ACCESS_TOKEN not set. Exiting.\")\n", + " raise ValueError(\"Set GITHUB_ACCESS_TOKEN environment variable\")\n", + "\n", + "client = github_utils.GitHubAPI(access_token=access_token).get_client()" + ] + }, + { + "cell_type": "markdown", + "id": "4cc7efd4-af91-44e8-9e3c-2bdbc8440c9d", + "metadata": {}, + "source": [ + "\n", + "## Pre-feth all the data you need in cache " + ] + }, + { + "cell_type": "markdown", + "id": "a7772ca8-b716-412a-8526-74977f0c3ae5", + "metadata": {}, + "source": [ + "\n", + "### Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period \n", + "- Prs opened in the repo\n", + "- Commits done\n", + "- LOC [additions and deletions]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0002b5e0-6975-4058-b9cd-b06676c89d38", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:github_utils:Starting prefetch for repo helpers.\n", + "INFO:github_utils:Fetched 6 commits for causify-ai/helpers user=tkpratardan.\n", + "INFO:github_utils:Found 7 PRs for causify-ai/helpers user=tkpratardan.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/helpers user=tkpratardan entries=6.\n", + "INFO:github_utils:Fetched 0 commits for causify-ai/helpers user=Prahar08modi.\n", + "INFO:github_utils:Found 0 PRs for causify-ai/helpers user=Prahar08modi.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/helpers user=Prahar08modi entries=0.\n", + "INFO:github_utils:Starting prefetch for repo tutorials.\n", + "INFO:github_utils:Fetched 15 commits for causify-ai/tutorials user=tkpratardan.\n", + "INFO:github_utils:Found 19 PRs for causify-ai/tutorials user=tkpratardan.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/tutorials user=tkpratardan entries=15.\n", + "INFO:github_utils:Fetched 6 commits for causify-ai/tutorials user=Prahar08modi.\n", + "INFO:github_utils:Found 7 PRs for causify-ai/tutorials user=Prahar08modi.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/tutorials user=Prahar08modi entries=6.\n", + "INFO:github_utils:Starting prefetch for repo cmamp.\n", + "INFO:github_utils:Fetched 6 commits for causify-ai/cmamp user=tkpratardan.\n", + "INFO:github_utils:Found 5 PRs for causify-ai/cmamp user=tkpratardan.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/cmamp user=tkpratardan entries=6.\n", + "INFO:github_utils:Fetched 0 commits for causify-ai/cmamp user=Prahar08modi.\n", + "INFO:github_utils:Found 0 PRs for causify-ai/cmamp user=Prahar08modi.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/cmamp user=Prahar08modi entries=0.\n", + "INFO:github_utils:Prefetched 6 user-repo combos in 92.79 seconds for period 2025-01-01 00:00:00+00:00 to 2025-05-24 00:00:00+00:00.\n" + ] + } + ], + "source": [ + "github_utils.prefetch_periodic_user_repo_data(\n", + " client,\n", + " org=\"causify-ai\",\n", + " repos=[\"helpers\",\"tutorials\",\"cmamp\"],\n", + " users=[\"tkpratardan\",\"Prahar08modi\"],\n", + " period=(\n", + " datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc),\n", + " datetime.datetime(2025, 5, 24, tzinfo=datetime.timezone.utc),\n", + " ),\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "4e6e1277-32f0-4fca-9c62-6f29eebb6a44", + "metadata": {}, + "source": [ + "\n", + "## Combine the data for statistics and visualizations" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d03e07fc-37f6-4d69-8c16-2bc4296d0334", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144 (no data).\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144 (no data).\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n" + ] + } + ], + "source": [ + "combined = github_utils.collect_all_metrics(\n", + " client, org=\"causify-ai\",\n", + " repos=[\"helpers\",\"tutorials\",\"cmamp\"],\n", + " users=[\"Prahar08modi\",\"tkpratardan\"],\n", + " period=(datetime.datetime(2025,1,1, tzinfo=datetime.timezone.utc),\n", + " datetime.datetime(2025,5,24, tzinfo=datetime.timezone.utc)),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "eb0aa61c-60f4-4b85-841a-623e3d069913", + "metadata": {}, + "source": [ + "\n", + "## Compare users on a repo based on `commits`, `prs`, `additions` and `deletions`" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "62bfd155-8e08-4ddb-82a2-3ec9d9a2c9ca", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ytnZWb/88ouefPJJPfTQQ+revbtq1KihH3/8kbnscM8R7EzEw8PD2ju2evVq7du3z9o7Jv0zDceYMWO0a9cuLV26VImJierSpUum47zxxhuaPHmytm3bpkKFCqlbt27WdRcvXlTz5s21evVq7dy5U82aNVNMTIyOHDlic4x33nlHVatW1c6dOzVixAht3LhRvr6+qlmzpnWbyMhIOTk5afPmzZKkGjVqyMnJSbNnz1ZaWpqSk5P16aefKjIyUi4uLtb9Dh48qO+++05xcXFasGCB/ve//6lFixb666+/tG7dOk2cOFHDhw+3Hjc9PV2tWrXS+fPntW7dOq1cuVJ//vmn2rdvbz3m559/rtjYWI0bN07btm1TyZIl9cEHH9zhOwLALBo2bCjDMDI95syZIw8PD8XHx+v06dO6du2aEhMT9dFHHykgIMDeZaMAcszBWMgVwzC0evVqxcfHq3///jpz5oyKFCmi//u//5Orq6t1u5sDWunSpfXee++pVq1aunjxos04t7Fjx6pBgwaSpKFDh6pFixa6evWq3N3dVbVqVVWtWtW67ZgxY7RkyRItW7ZM/fr1s7Y3btxYr7zyinV50aJF8vf3t6m7UKFCKlasmE6ePClJCgsL0/fff6927dqpV69eSktLU926dbVixQqb/dLT0zVr1ix5eXkpPDxcjRo10r59+7RixQo5OTmpfPnymjhxotasWaM6depo9erV+vXXX3Xo0CEFBwdLkj755BNFRERo69atqlWrlqZOnaru3bure/fukqS33npLq1atytRrBwCAI6PH7j62fPlyeXp6yt3dXdHR0Wrfvr1iY2Ml/XO7/c2hTvrnUmdMTIxCQkLk5eVlDW//7m2rUqWK9eeMgb8Zl2wvXryowYMHq2LFivL19ZWnp6f27NmT6Rg398zl1MmTJ9WjRw917txZW7du1bp16+Tq6qq2bdva3LQQGhoqLy8v63JAQIDCw8Pl5ORk05ZR8549exQcHGwNdZIUHh4uX19f7dmzx7pNnTp1bOqpW7durp8DAAD2RI/dfaxRo0aaOXOmXF1dFRQUZHM3bJEiRWy2vXTpkqKiohQVFaV58+bJz89PR44cUVRUVKabK26+7Jkx6W56erokafDgwVq5cqXeeecdlS1bVh4eHmrbtm2mY/z7/IGBgZnG8924cUPnz5+3fgXPjBkz5OPjo7ffftu6zWeffabg4GBt3rxZjzzySKb6MmrMqi2jZuCui/WxdwUA7CU22d4V2KDH7j5WpEgRlS1bViEhIbed4mTv3r06d+6cJkyYoMcee0wVKlTI8saJ29mwYYO6dOmiNm3aqHLlygoMDFRiYuJt96tbt66SkpK0fft2a9sPP/yg9PR0a0/Z5cuXbXrdJFlnbL+TkFaxYkUdPXpUR48etbb9/vvvSkpKUnh4uHWbjDF5GTZt2pTncwIAYA8EuwIiJCRErq6umj59uv78808tW7ZMY8aMyfVxypUrp6+++koJCQnatWuXnnvuuRyFrooVK6pZs2bq0aOHtmzZog0bNqhfv37q0KGDgoKCJEktWrTQ1q1b9eabb2r//v3asWOHunbtqlKlSlnvRMuLyMhIVa5cWR07dtSOHTu0ZcsWderUSQ0aNLBeMn7ppZc0a9YszZ49W3/88Yd1Lj0AAO4nBLsCws/PT3PmzNHixYsVHh6uCRMm6J133sn1caZMmaKiRYuqXr16iomJUVRUlB5++OEc7Ttv3jxVqFBBTzzxhJo3b65HH31UH330kXV948aNNX/+fC1dulTVq1dXs2bN5Obmpri4OHl4eOS61gwWi0Vff/21ihYtqscff1yRkZEqXbq0Fi1aZN2mffv2GjFihF599VXVqFFDhw8fVu/evfN8TgAA7MFimHwq/ZSUFPn4+Cg5OVne3t42665evapDhw4pLCxM7u7udqoQZsHnqQBjjB1QcN2DMXa3yjL/Ro8dAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsTGLt2rWyWCxKSkqydyl3hdmfHwAA+aGQvQtwSPf664Hy8HUkDRs2VLVq1TR16tT8rycPQkNDNXDgQA0cONDepQAAUGDRY4dsGYahGzdu3NNzXrt27Z6eDwAAMyHY3Ye6dOmidevWadq0abJYLLJYLEpMTLTZ5vLly4qOjlb9+vWVlJSkxMREWSwWLVy4UPXq1ZO7u7sqVaqkdevWWffJuNz53XffqUaNGnJzc9NPP/2kgwcPqlWrVgoICJCnp6dq1aqlVatWWfdr2LChDh8+rJdfftlajySdO3dOzz77rB544AEVLlxYlStX1oIFC2zqbNiwofr166eBAweqRIkSioqKkiStWLFCDz30kDw8PNSoUaNMzy+nxx4wYIBeffVVFStWTIGBgYqNjb3DVx8AAMdFsLsPTZs2TXXr1lWPHj104sQJnThxQsHBwdb1SUlJatKkidLT07Vy5Ur5+vpa1w0ZMkSvvPKKdu7cqbp16yomJkbnzp2zOf7QoUM1YcIE7dmzR1WqVNHFixfVvHlzrV69Wjt37lSzZs0UExOjI0eOSJK++uorPfjgg3rzzTet9UjS1atXVaNGDX377bfavXu3evbsqRdeeEFbtmyxOd/cuXPl6uqqDRs26MMPP9TRo0f11FNPKSYmRgkJCXrxxRc1dOhQm31yc+wiRYpo8+bNevvtt/Xmm29q5cqVd/weAADgiBhjdx/y8fGRq6urChcurMDAQEnS3r17JUknT55U+/btVa5cOc2fP1+urq42+/br109PP/20JGnmzJmKi4vT//73P7366qvWbd588001adLEulysWDFVrVrVujxmzBgtWbJEy5YtU79+/VSsWDE5OzvLy8vLWo8kPfDAAxo8eLB1uX///oqPj9fnn3+u2rVrW9vLlSunt99+27r8+uuvq0yZMpo8ebIkqXz58vr11181ceLEXB+7SpUqGjVqlPU877//vlavXm3z/AAAMAuCnck0adJEtWvX1qJFi+Ts7Jxpfd26da0/FypUSDVr1tSePXtstqlZs6bN8sWLFxUbG6tvv/1WJ06c0I0bN3TlyhVrj1120tLSNG7cOH3++ec6duyYrl27ptTUVBUuXNhmuxo1atgs79mzR3Xq1Mm27twcu0qVKjbLJUuW1OnTp29ZNwAA9yu7Xopdv369YmJiFBQUJIvFoqVLl2a77X/+8x9ZLBaHuQvUUbVo0ULr16/X77//nudjFClSxGZ58ODBWrJkicaNG6cff/xRCQkJqly58m1vdJg0aZKmTZum1157TWvWrFFCQoKioqIy7ffv8+VETo/t4uJis2yxWJSenp7r8wEAcD+wa7C7dOmSqlatqhkzZtxyuyVLlmjTpk0KCgq6R5U5PldXV6WlpWVqnzBhgjp37qwnnngiy3C3adMm6883btzQ9u3bVbFixVuea8OGDerSpYvatGmjypUrKzAwMNPNDFnVs2HDBrVq1UrPP/+8qlatqtKlS+uPP/647XOrWLFiprFyN9d9J8cGAMDM7BrsoqOj9dZbb6lNmzbZbnPs2DH1799f8+bN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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "helpers_summary = github_utils.summarize_user_metrics_for_repo(\n", + " combined,\n", + " repo=\"tutorials\",\n", + ")\n", + "github_utils.plot_metrics_by_user(\n", + " helpers_summary,\n", + " repo=\"tutorials\",\n", + " metrics=['commits'],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "5b57c41c-163d-4aac-b55b-b223ae9de9a1", + "metadata": {}, + "source": [ + "\n", + "## See stats of a user on multiple repos based on `commits`, `prs`, `additions` and `deletions`" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ce513fe8-1b34-4679-b3a9-fe00aa1b62a6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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fYzjx49XZGRkrutcG0iL02uvvaYhQ4Zo2bJl+uabbzR27FjFxsZq69attgd/UDIIdihR/fr100MPPaStW7fq008/zXO5OnXqaO3atWrXrt11/+EojqE2si/17dq1q1Afbr6+vvLy8tKuXbvyXS4oKEj79u3L0Z59Wau4x4Hbv39/jrbff/9dFStWtIXizz//XNHR0Xrttddsy1y+fDnXJxcL69Zbb9Wtt96qF198UQsXLtR9992nTz75RMOHD1dQUJDWrl2r8+fP2/XaldS5uFZJvRcF+cf8448/Vp8+fTRgwACtXLnS9gT332X3rPx9e7///rukvx5Cup6Cvq951bt+/XqdOXNGS5YsUYcOHWztCQkJ1913tqCgIMXFxSktLc0uzF973s+dO6e4uDhNmTLF7gGg3H5+b8Svv/6q33//XQsWLLB7kObay5whISGSdN3f57wEBQUpKytL+/fvt/UAS389sJOcnJzjZyu/3xPpr56v3r17q3fv3srKytIjjzyid999VxMnTix0CMs+NhcXF0VERBRonf3796tz58626bS0NB07dkw9evSwHa/01/uavX3prxEPEhIScuwnPDxc4eHhev7557V582a1a9dO77zzjl544YVCHQsKh0uxKFEeHh6aM2eOYmJi1Lt37zyXGzhwoDIzMzVt2rQc865evWr3j1SlSpVuOIx069ZNnp6eio2N1eXLl+3m5dcT4OTkpL59++p///ufduzYkWN+9ro9evTQtm3btGXLFtu8Cxcu6L333lPt2rXVsGHDG6r/Wlu2bLG7P+nw4cNatmyZunXrZuvxcHZ2znFsM2fOzDGkRWGcO3cuxzabNWsmSbbLTD169FBmZqZmzZplt9wbb7whi8Vie2q6pJTUe5H9FHF+P4uurq5asmSJWrVqpd69e2vbtm05ljl69Kjt6UlJSk1N1QcffKBmzZoVaLzHgr6vlSpVyrXe7J+Pv28jIyNDb7/99nX3na1Hjx66evWq5syZY2vLzMzUzJkzr7svScX+1W+57ccwjBxDh/j6+qpDhw6aO3eukpKS7OYVpIc4O/BcW//rr78uSerZs6ekgv2eXDvci5OTk+0p62uHTimI6tWrq1OnTnr33Xd17NixHPOzb9H4u/fee8/uHsA5c+bo6tWrtt/RiIgIubq66q233rI7nv/+979KSUmxHW9qamqO+4DDw8Pl5ORUpGNB4dBjhxKX25AH1+rYsaMeeughxcbGKj4+Xt26dZOLi4v279+vxYsX680337Tdn9eiRQvNmTNHL7zwgurWravq1avr9ttvL1RNXl5eeuONNzR8+HC1atXKNjbVzz//rIsXL+Z76eOll17SN998o44dO2rkyJFq0KCBjh07psWLF2vTpk3y8fHRs88+axvqZezYsapSpYoWLFighIQEffHFF3Y3HheHxo0bKzIy0m64E+mvMday9erVSx9++KG8vb3VsGFDbdmyRWvXrs1zCJGCWLBggd5++23169dPderU0fnz5/X+++/Ly8vL9o9e79691blzZ/3rX/9SYmKimjZtqm+++UbLli3T448/bvegREkoqffC3d1dDRs21Keffqp69eqpSpUqaty4cY77tdzd3bV8+XLdfvvtioqK0oYNG+yWqVevnh588EFt375dfn5+mjt3rk6cOKF58+YVqI6Cvq/NmjWTs7OzXn75ZaWkpMhqter2229X27ZtVblyZUVHR2vs2LGyWCz68MMPC3Xpu3fv3mrXrp2effZZJSYm2sbiu/aeKi8vL3Xo0EHTp0/XlStXVKtWLX3zzTeF6h0siPr166tOnToaP368/vzzT3l5eemLL77I9b68t956S+3bt9fNN9+skSNHKjg4WImJifr6668VHx+f736aNm2q6Ohovffee7ZL2tu2bdOCBQvUt29fW+9XQX5Phg8frrNnz+r222/XTTfdpEOHDmnmzJlq1qyZXW9gYcyePVvt27dXeHi4RowYoZCQEJ04cUJbtmzRkSNH9PPPP9stn5GRoS5dumjgwIHat2+f3n77bbVv31533HGHpL+C8IQJEzRlyhR1795dd9xxh225Vq1a2e7L/PbbbzVmzBgNGDBA9erV09WrV/Xhhx/K2dlZd911V5GOBYVQqs/gwvT+PtxJfq4d7iTbe++9Z7Ro0cJwd3c3PD09jfDwcOPpp582jh49alvm+PHjRs+ePQ1PT09Dkm3ok/z2fe0wHdm++uoro23btoa7u7vh5eVl3HLLLcaiRYuue5yHDh0yBg8ebPj6+hpWq9UICQkxRo8ebaSnp9uWOXjwoNG/f3/Dx8fHcHNzM2655RZj+fLldtvJHmLj2mEB8jqW7GEXTp06ZWvT/x/i46OPPjJCQ0MNq9VqNG/ePMewFufOnTOG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770nHx8fbdiwQb169bK1Dx06VAMHDpQkPfPMM2rTpo0mTpxot6+hQ4fabevy5cv64IMPVKtWLUnSzJkz1bNnT7322mvy9/cvprNSMPTYAQCAMmXPnj1KT09Xly5d8lymSZMmtr9n9+SFh4fbtWV/TZf01/dWjxgxQqGhofL29paXl5fS0tKUlJRU6O1evnxZqamptrbAwEBbqJOkNm3aKCsrS/v27SvwMRcXeuwAkwhfEH79haBfo391dAkAriP7K7by4+LiYvt79uC+17ZlZWXZpqOjo3XmzBm9+eabCgoKktVqVZs2bZSRkVHo7Uqy23ZZQo8dAAAoU0JDQ+Xu7q64uLhi2+b333+vsWPHqkePHmrUqJGsVqtOnz5dLNtOSkrS0aNHbdNbt26Vk5OTwsLCimX7hUGPHQAAKFPc3Nz0zDPP6Omnn5arq6vatWunU6dO6bfffsv38mx+QkND9eGHH6ply5ZKTU3VU089VaCewYLWGx0drVdffVWpqakaO3asBg4cWOr310kEOwAAUAZNnDhRFSpU0KRJk3T06FHVqFFDDz/8cJG399///lcjR47UzTffrICAAL300ksaP358sdRat25d3XnnnerRo4fOnj2rXr166e233y6WbReWxTAMwyF7LsNSU1Pl7e2tlJQUeXl5ObocoEC4x65guMcO/ySXL19WQkKCgoOD5ebm5uhyTCkmJkZLly5VfHz8DW0nv/eqMLmEe+wAAABMgmAHAABgEgQ7AACAIoqJibnhy7DFiWAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAChTOnXqpMcff7zI68fExKhZs2bFVk95wnfFAgDwTxPjXcr7Synd/f2D0WMHAABQSIZh6OrVq44uIweCHQAAKHOysrL09NNPq0qVKvL391dMTIxtXnJysoYPHy5fX195eXnp9ttv188//5zntoYMGaK+fftqypQptnUefvhhZWRk2O0vNjZWwcHBcnd3V9OmTfX555/b5q9fv14Wi0UrV65UixYtZLVatWnTJv3888/q3LmzPD095eXlpRYtWmjHjh0lck4KgkuxAACgzFmwYIHGjRunH374QVu2bNGQIUPUrl07de3aVQMGDJC7u7tWrlwpb29vvfvuu+rSpYt+//13ValSJdftxcXFyc3NTevXr1diYqKGDh2qqlWr6sUXX5QkxcbG6qOPPtI777yj0NBQbdy4Uffff798fX3VsWNH23aeffZZvfrqqwoJCVHlypXVoUMHNW/eXHPmzJGzs7Pi4+Pl4uJSKucoNwQ7AABQ5jRp0kSTJ0+WJIWGhmrWrFmKi4uTu7u7tm3bppMnT8pqtUqSXn31VS1dulSff/65Ro4cmev2XF1dNXfuXFWsWFGNGjXS1KlT9dRTT2natGm6cuWKXnrpJa1du1Zt2rSRJIWEhGjTpk1699137YLd1KlT1bVrV9t0UlKSnnrqKdWvX99WqyMR7AAAQJnTpEkTu+kaNWro5MmT+vnnn5WWlqaqVavazb906ZIOHjyY5/aaNm2qihUr2qbbtGmjtLQ0HT58WGlpabp48aJdYJOkjIwMNW/e3K6tZcuWdtPjxo3T8OHD9eGHHyoiIkIDBgxQnTp1CnWsxYlgBwAAypxrL2daLBZlZWUpLS1NNWrU0Pr163Os4+PjU6R9paWlSZK+/vpr1apVy25edq9gtkqVKtlNx8TE6N5779XXX3+tlStXavLkyfrkk0/Ur1+/ItVyowh2AACg3Lj55pt1/PhxVahQQbVr1y7wej///LMuXbokd3d3SdLWrVvl4eGhgIAAValSRVarVUlJSXaXXQuqXr16qlevnp544gkNGjRI8+bNI9gBAABcT0REhNq0aaO+fftq+vTpqlevno4ePaqvv/5a/fr1y3GpNFtGRoYefPBBPf/880pMTNTkyZM1ZswYOTk5ydPTU+PHj9cTTzyhrKwstW/fXikpKfr+++/l5eWl6OjoXLd56dIlPfXUU+rfv7+Cg4N15MgRbd++XXfddVdJnoJ8EewAAEC5YbFYtGLFCv3rX//S0KFDderUKfn7+6tDhw7y8/PLc70uXbooNDRUHTp0UHp6ugYNGmQ3hMq0adPk6+ur2NhY/fHHH/Lx8dHNN9+s5557Ls9tOjs768yZMxo8eLBOnDihatWq6c4779SUKVOK85ALxWIYhuGonW/cuFGvvPKKfvzxRx07dkxffvml+vbt+3/FWSy5rjd9+nQ99dRTuc6LiYnJcULDwsK0d+/eAteVmpoqb29vpaSkyMvLq8DrAY4UviDc0SWUC79G/+roEoBSc/nyZSUkJCg4OFhubm6OLsdhhgwZouTkZC1dutTRpeQpv/eqMLnEoQMUX7hwQU2bNtXs2bNznX/s2DG719y5c2WxWK7bxdmoUSO79TZt2lQS5QMAAJQpDr0UGxUVpaioqDzn+/v7200vW7ZMnTt3VkhISL7brVChQo51AQAAzK7c3GN34sQJff3111qwYMF1l92/f79q1qwpNzc3tWnTRrGxsQoMDCyFKgEAQFkzf/58R5dQaspNsFuwYIE8PT1155135rtc69atNX/+fIWFhenYsWOaMmWKbrvtNu3atUuenp65rpOenq709HTbdGpqarHWDgAAUBrKTbCbO3eu7rvvvuve/Pn3S7tNmjRR69atFRQUpM8++0wPPvhgruvExsY69AkWAACA4uDQhycK6rvvvtO+ffs0fPjwQq/r4+OjevXq6cCBA3kuM2HCBKWkpNhehw8fvpFyAQAAHKJcBLv//ve/atGihZo2bVroddPS0nTw4EHVqFEjz2WsVqu8vLzsXgAAAOWNQ4NdWlqa4uPjFR8fL0lKSEhQfHy8kpKSbMukpqZq8eLFefbWdenSRbNmzbJNjx8/Xhs2bFBiYqI2b96sfv36ydnZWYMGDSrRYwEAAHA0h95jt2PHDnXu3Nk2PW7cOElSdHS07QmWTz75RIZh5BnMDh48qNOnT9umjxw5okGDBunMmTPy9fVV+/bttXXrVvn6+pbcgQAAAJQBDg12nTp10vW++GLkyJEaOXJknvMTExPtpj/55JPiKA0AAPyDderUSc2aNdOMGTMKtPz69evVuXNnnTt3Tj4+PiVaW37KzVOxAACgeJT2VxAW9qv8ChuqpL++UnTp0qW227tu1JIlS+Ti4lIs2ypNBDsAAID/LyMjQ66urqpSpYqjSymScvFULAAA+GcYMmSINmzYoDfffFMWi0UWi0Xz58/PcXlz6dKlslgskv76ZokpU6bo559/tltHkpKSktSnTx95eHjIy8tLAwcO1IkTJ2zbiYmJUbNmzfSf//xHwcHBtvFyO3XqpMcff9y23IcffqiWLVvK09NT/v7+uvfee3Xy5Mk8j+PQoUPq3bu3KleurEqVKqlRo0ZasWJF8ZykfNBjBwAAyow333xTv//+uxo3bqypU6dKkr7++ut817n77ru1a9curVq1SmvXrpUkeXt7KysryxbqNmzYoKtXr2r06NG6++67tX79etv6Bw4c0BdffKElS5bI2dk5131cuXJF06ZNU1hYmE6ePKlx48Zp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PXu2Lly4kGN+cnKyGjRokOMetd27dys5OVkNGzYszXJz5erqqszMzBztXl5euvvuu/X+++/r008/1RdffKGzZ886oEKUFO6xA27Q8uXL9ccff6hDhw6qXLmyVqxYoaysLNsTswDKn9mzZ6tdu3a65ZZbNHXqVDVp0kRXr17VmjVrNGfOHO3evVvh4eG67777NGPGDF29elWPPPKIOnbsqJYtWzq6fNWuXVurV6/Wvn37VLVqVXl7e2vmzJmqUaOGmjdvLicnJy1evFj+/v7y8fFxdLkoRvTYATfIx8dHS5Ys0e23364GDRronXfe0aJFi9SoUSNHlwagiEJCQrRz50517txZTz75pBo3bqyuXbsqLi5Oc+bMkcVi0bJly1S5cmV16NBBERERCgkJ0aeffuro0iVJI0aMUFhYmFq2bClfX199//338vT01PTp09WyZUu1atVKiYmJtoc4YB4WoyB3iQIAAKDMI6YDAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMIn/B49RngmZVFdjAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "krishna_summary = github_utils.summarize_repo_metrics_for_user(\n", + " combined,\n", + " user=\"tkpratardan\",\n", + ")\n", + "\n", + "# then plot PRs and commits across their repos\n", + "github_utils.plot_metrics_by_repo(\n", + " krishna_summary,\n", + " user=\"tkpratardan\",\n", + " metrics=['prs', 'commits'],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0bfdaf57-a6f3-4620-bfd8-c539cb1f0ffc", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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/vgDu3btwtGjR0s8xzlz5sDFxQX169dHVlYWwsLCYG9vX+LtiahoWVlZSExMRF5eHpKSknDo0CEEBQWhS5cuGDhwINTU1ODq6gpvb28sWrQIdevWxaNHj7B//35079690Es2AgMDMW7cOOjr66NTp07IysrC+fPn8ezZM0yaNAkmJibQ1tbGoUOHUKNGDWhpaSl9flWpUgWjRo3C1KlTYWRkBCsrKyxatAgvXryAn59fieb28uVLTJ06FT179oSNjQ0ePnyIqKgo+Pj4lMlrRxWDR+xIpW3atAnu7u5KH4rAq2B3/vx52NvbY/bs2Zg2bRpcXFxw//59jBo1SqHt5MmTMWDAAPj6+sLV1RV6enpvPVUxb948xMXFwdbWFsbGxoW28fb2xsqVK7FkyRLUr18f33//PYKDg8XlDUpCKpVi5syZaNiwIdq0aQN1dXVs3769xNsTUdEOHToEc3Nz1KxZE506dcLx48exatUq7N27F+rq6pBIJDhw4ADatGmDwYMHo27duujTpw/u378PU1PTQvscOnQofvzxRwQHB8PR0RFt27ZFSEiIeMROQ0MDq1atwvfffw8LCwt069at0H4WLlwIHx8fDBgwAI0bN8adO3dw+PBhGBoalmhu6urqePLkCQYOHIi6deuid+/e8PT0RGBg4Lu9WFQpSAThjcW4iIiIiOijxCN2RERERCqCwY6IiIhIRTDYEREREakIBjsiIiIiFcFgR0RERKQiGOyIiIiIVASDHREREZGKYLAjIiIiUhEMdkREREQqgsGOiIiISEUw2BERERGpCAY7IiIiIhXx/wDda/oNJ3A+FAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "krishna_summary_2 = github_utils.summarize_repo_metrics_for_user(\n", + " combined,\n", + " user=\"tkpratardan\",\n", + ")\n", + "\n", + "github_utils.plot_metrics_by_repo(\n", + " krishna_summary_2,\n", + " user=\"tkpratardan\",\n", + " metrics=['additions', 'deletions'],\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "94679d8c-745d-4679-b44d-e2f04951d8cb", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n" + ] + } + ], + "source": [ + "krishna_daily_commits = github_utils.build_daily_commit_df(\n", + " client, org=\"causify-ai\",\n", + " repo=\"helpers\",\n", + " username=\"tkpratardan\",\n", + " period=(datetime.datetime(2025,1,1, tzinfo=datetime.timezone.utc),\n", + " datetime.datetime(2025,5,24, tzinfo=datetime.timezone.utc)),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "74b56187-49d3-4213-8d52-73dd0d2004ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datecommitsrepouser
02025-01-010helperstkpratardan
12025-01-020helperstkpratardan
22025-01-030helperstkpratardan
32025-01-040helperstkpratardan
42025-01-050helperstkpratardan
52025-01-060helperstkpratardan
62025-01-070helperstkpratardan
72025-01-080helperstkpratardan
82025-01-090helperstkpratardan
92025-01-100helperstkpratardan
102025-01-111helperstkpratardan
112025-01-120helperstkpratardan
122025-01-130helperstkpratardan
132025-01-140helperstkpratardan
142025-01-150helperstkpratardan
152025-01-161helperstkpratardan
162025-01-170helperstkpratardan
172025-01-180helperstkpratardan
182025-01-190helperstkpratardan
192025-01-200helperstkpratardan
202025-01-211helperstkpratardan
212025-01-220helperstkpratardan
222025-01-231helperstkpratardan
232025-01-240helperstkpratardan
242025-01-250helperstkpratardan
\n", + "
" + ], + "text/plain": [ + " date commits repo user\n", + "0 2025-01-01 0 helpers tkpratardan\n", + "1 2025-01-02 0 helpers tkpratardan\n", + "2 2025-01-03 0 helpers tkpratardan\n", + "3 2025-01-04 0 helpers tkpratardan\n", + "4 2025-01-05 0 helpers tkpratardan\n", + "5 2025-01-06 0 helpers tkpratardan\n", + "6 2025-01-07 0 helpers tkpratardan\n", + "7 2025-01-08 0 helpers tkpratardan\n", + "8 2025-01-09 0 helpers tkpratardan\n", + "9 2025-01-10 0 helpers tkpratardan\n", + "10 2025-01-11 1 helpers tkpratardan\n", + "11 2025-01-12 0 helpers tkpratardan\n", + "12 2025-01-13 0 helpers tkpratardan\n", + "13 2025-01-14 0 helpers tkpratardan\n", + "14 2025-01-15 0 helpers tkpratardan\n", + "15 2025-01-16 1 helpers tkpratardan\n", + "16 2025-01-17 0 helpers tkpratardan\n", + "17 2025-01-18 0 helpers tkpratardan\n", + "18 2025-01-19 0 helpers tkpratardan\n", + "19 2025-01-20 0 helpers tkpratardan\n", + "20 2025-01-21 1 helpers tkpratardan\n", + "21 2025-01-22 0 helpers tkpratardan\n", + "22 2025-01-23 1 helpers tkpratardan\n", + "23 2025-01-24 0 helpers tkpratardan\n", + "24 2025-01-25 0 helpers tkpratardan" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "krishna_daily_commits[0:25]" + ] + }, + { + "cell_type": "markdown", + "id": "6d1814db-b00f-4d7f-b39d-4568a5abeb4c", + "metadata": {}, + "source": [ + "\n", + "## There are many more helper funcs to see and compare statistics. Look at github_utils for more info -> `tutorial_github_causify_style/github_utils.py`" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From a43a53ba74a009abd89204544c5c7f66895ae233 Mon Sep 17 00:00:00 2001 From: shaunak01 Date: Sat, 24 May 2025 22:46:15 +0000 Subject: [PATCH 2/8] Fix --- tutorial_github_causify_style/github_utils.py | 719 ++++++++++++++++-- 1 file changed, 649 insertions(+), 70 deletions(-) diff --git a/tutorial_github_causify_style/github_utils.py b/tutorial_github_causify_style/github_utils.py index 59fc084402..c02a53b2ab 100644 --- a/tutorial_github_causify_style/github_utils.py +++ b/tutorial_github_causify_style/github_utils.py @@ -1,13 +1,25 @@ +""" +Import as: + +import tutorial_github_causify_style.github_utils as tgcsgiut +""" + import datetime import logging import os +import time as time_module +from datetime import date, timezone from typing import Any, Dict, List, Optional, Tuple import github +import helpers.hcache_simple as hcacsimp +import matplotlib.pyplot as plt +import pandas as pd from tqdm import tqdm _LOG = logging.getLogger(__name__) + # ############################################################################# # GitHubAPI # ############################################################################# @@ -15,14 +27,15 @@ class GitHubAPI: """ - A class to initialize and manage authentication with the GitHub API using PyGithub. + A class to initialize and manage authentication with the GitHub API using + PyGithub. """ def __init__( self, access_token: Optional[str] = None, base_url: Optional[str] = None ): """ - Initialize the GitHub API client + Initialize the GitHub API client. :param access_token: github personal access token; if not provided, it is fetched from the environment variable `GITHUB_ACCESS_TOKEN` @@ -42,7 +55,7 @@ def __init__( def get_client(self) -> github.Github: """ - Return the authenticated GitHub client + Return the authenticated GitHub client. :return: an instance of the authenticated PyGithub client """ @@ -50,7 +63,7 @@ def get_client(self) -> github.Github: def close_connection(self) -> None: """ - Close the GitHub API connection + Close the GitHub API connection. """ self.github.close() @@ -63,7 +76,7 @@ def close_connection(self) -> None: # TODO(prahar08modi): Test the function using pytest def get_repo_names(client: github.Github, org_name: str) -> Dict[str, List[str]]: """ - Retrieve a list of repositories under a specific organization + Retrieve a list of repositories under a specific organization. :param client: authenticated instance of the PyGithub client :param org_name: name of the GitHub organization @@ -76,7 +89,9 @@ def get_repo_names(client: github.Github, org_name: str) -> Dict[str, List[str]] owner = client.get_organization(org_name) except Exception as e: _LOG.error("Error retrieving organization '%s': %s", org_name, e) - raise ValueError(f"'{org_name}' is not a valid GitHub organization.") from e + raise ValueError( + f"'{org_name}' is not a valid GitHub organization." + ) from e repos = [repo.name for repo in owner.get_repos()] result = {"owner": org_name, "repositories": repos} return result @@ -87,7 +102,7 @@ def get_github_contributors( client: github.Github, repo_names: List[str] ) -> Dict[str, List[str]]: """ - Retrieve GitHub usernames contributing to specified repositories + Retrieve GitHub usernames contributing to specified repositories. :param client: authenticated instance of the PyGithub client :param repo_names: repository names in the format 'owner/repo' to fetch @@ -105,9 +120,7 @@ def get_github_contributors( ] result[repo_name] = contributors except Exception as e: - _LOG.error( - "Error fetching contributors for %s: %s", repo_name, e - ) + _LOG.error("Error fetching contributors for %s: %s", repo_name, e) result[repo_name] = [] return result @@ -116,11 +129,11 @@ def normalize_period_to_utc( period: Optional[Tuple[datetime.datetime, datetime.datetime]], ) -> Tuple[Optional[datetime.datetime], Optional[datetime.datetime]]: """ - Convert a datetime period to UTC and ensure both dates are timezone-aware + Convert a datetime period to UTC and ensure both dates are timezone-aware. :param period: start and end datetime - :return: tuple of UTC-aware start and end datetime, or (None, None) if - period is None + :return: tuple of UTC-aware start and end datetime, or (None, None) + if period is None """ if not period: return None, None @@ -148,7 +161,7 @@ def get_total_commits( """ Fetch the number of commits made in the repositories of the specified organization, optionally filtered by GitHub usernames and a specified time - period + period. :param client: authenticated instance of the PyGithub client :param org_name: name of the GitHub organization @@ -166,9 +179,7 @@ def get_total_commits( repos_info = get_repo_names(client, org_name) repositories = repos_info.get("repositories", []) except Exception as e: - _LOG.error( - "Error retrieving repositories for '%s': %s", org_name, e - ) + _LOG.error("Error retrieving repositories for '%s': %s", org_name, e) return { "total_commits": 0, "period": "N/A", @@ -214,12 +225,12 @@ def get_total_prs( org_name: str, usernames: Optional[List[str]] = None, period: Optional[Tuple[datetime.datetime, datetime.datetime]] = None, - state: str = "open", + state: str = "all", ) -> Dict[str, Any]: """ Fetch the number of pull requests made in the repositories of the specified - organization, optionally filtered by GitHub usernames, a specified time period, - and the state of the pull requests + organization, optionally filtered by GitHub usernames, a specified time + period, and the state of the pull requests. :param client: authenticated instance of the PyGithub client :param org_name: name of the GitHub organization @@ -238,9 +249,7 @@ def get_total_prs( repos_info = get_repo_names(client, org_name) repositories = repos_info.get("repositories", []) except Exception as e: - _LOG.error( - "Error retrieving repositories for '%s': %s", org_name, e - ) + _LOG.error("Error retrieving repositories for '%s': %s", org_name, e) return {"total_prs": 0, "period": "N/A", "prs_per_repository": {}} total_prs = 0 prs_per_repository = {} @@ -253,37 +262,25 @@ def get_total_prs( try: repo = client.get_repo(f"{org_name}/{repo_name}") repo_pr_count = 0 - # Fetch pull requests based on the specified state. - issues = repo.get_issues(state=state, since=since) - for issue in issues: - if not issue.pull_request: - # Skip if not a pull request - continue - try: - pr = repo.get_pull(issue.number) - except Exception as e: - _LOG.warning( - "Could not fetch PR #%d in %s: %s", issue.number, repo_name, e - ) + pulls = repo.get_pulls(state=state) + for pr in pulls: + if usernames and pr.user.login not in usernames: continue - # Ensure pr.created_at is timezone-aware in UTC. pr_created_at = ( pr.created_at.replace(tzinfo=datetime.timezone.utc) if pr.created_at.tzinfo is None else pr.created_at.astimezone(datetime.timezone.utc) ) if since and until and not (since <= pr_created_at <= until): - # Skip pull request if it's outside the specified date range. - continue - if usernames and pr.user.login not in usernames: - # Skip pull request if it's not authored by one of the specified users. continue repo_pr_count += 1 prs_per_repository[repo_name] = repo_pr_count total_prs += repo_pr_count except Exception as e: _LOG.error( - "Error accessing pull requests for repository '%s': %s", repo_name, e + "Error accessing pull requests for repository '%s': %s", + repo_name, + e, ) prs_per_repository[repo_name] = 0 result = { @@ -301,8 +298,8 @@ def get_prs_not_merged( period: Optional[Tuple[datetime.datetime, datetime.datetime]] = None, ) -> Dict[str, Any]: """ - Fetch the count of closed but unmerged pull requests in the specified repositories - and by the specified GitHub users within a given period + Fetch the count of closed but unmerged pull requests in the specified + repositories and by the specified GitHub users within a given period. :param client: authenticated instance of the PyGithub client :param org_name: name of the GitHub organization @@ -319,9 +316,7 @@ def get_prs_not_merged( repos_info = get_repo_names(client, org_name) repositories = repos_info.get("repositories", []) except Exception as e: - _LOG.error( - "Error retrieving repositories for '%s': %s", org_name, e - ) + _LOG.error("Error retrieving repositories for '%s': %s", org_name, e) return { "prs_not_merged": 0, "period": "N/A", @@ -348,9 +343,7 @@ def get_prs_not_merged( for pr in pulls: try: # Print progress. - _LOG.debug( - "Processing PR #%d from %s", pr.number, repo_name - ) + _LOG.debug("Processing PR #%d from %s", pr.number, repo_name) # Ensure PR creation date is always set before usage. pr_created_at = ( pr.created_at if pr.created_at else datetime.datetime.min @@ -376,14 +369,19 @@ def get_prs_not_merged( except Exception as e: # Skip this PR and proceed with the next one. _LOG.error( - "Error processing PR #%d in '%s': %s", pr.number, repo_name, e + "Error processing PR #%d in '%s': %s", + pr.number, + repo_name, + e, ) continue prs_per_repository[repo_name] = repo_unmerged_pr_count total_unmerged_prs += repo_unmerged_pr_count except Exception as e: _LOG.error( - "Error accessing pull requests for repository '%s': %s", repo_name, e + "Error accessing pull requests for repository '%s': %s", + repo_name, + e, ) prs_per_repository[repo_name] = 0 result = { @@ -398,11 +396,12 @@ def get_total_issues( client: github.Github, org_name: str, repo_names: Optional[List[str]] = None, - state: str = "open", + state: str = "all", period: Optional[Tuple[datetime.datetime, datetime.datetime]] = None, ) -> Dict[str, Any]: """ - Retrieve the number of issues in the specified repositories within a given time range and state + Retrieve the number of issues in the specified repositories within a given + time range and state. :param client: authenticated instance of the PyGithub client :param org_name: name of the GitHub organization @@ -428,9 +427,7 @@ def get_total_issues( repos_info = get_repo_names(client, org_name) repo_names = repos_info.get("repositories", []) except Exception as e: - _LOG.error( - "Error retrieving repositories for '%s': %s", org_name, e - ) + _LOG.error("Error retrieving repositories for '%s': %s", org_name, e) return { "total_issues": 0, "state": state, @@ -452,7 +449,9 @@ def get_total_issues( continue # Ensure Issue creation date is timezone-aware in UTC. issue_created_at = ( - issue.created_at if issue.created_at else datetime.datetime.min + issue.created_at + if issue.created_at + else datetime.datetime.min ) if issue_created_at.tzinfo is None: issue_created_at = issue_created_at.replace( @@ -472,9 +471,7 @@ def get_total_issues( repo_issue_count += 1 except Exception as e: # Skip this issue and proceed with the next one. - _LOG.error( - "Error processing issue in '%s': %s", repo_name, e - ) + _LOG.error("Error processing issue in '%s': %s", repo_name, e) continue issues_per_repository[repo_name] = repo_issue_count total_issues += repo_issue_count @@ -526,9 +523,7 @@ def get_issues_without_assignee( repos_info = get_repo_names(client, org_name) repo_names = repos_info.get("repositories", []) except Exception as e: - _LOG.error( - "Error retrieving repositories for '%s': %s", org_name, e - ) + _LOG.error("Error retrieving repositories for '%s': %s", org_name, e) return { "issues_without_assignee": 0, "state": state, @@ -549,7 +544,9 @@ def get_issues_without_assignee( continue # Ensure Issue creation date is timezone-aware in UTC. issue_created_at = ( - issue.created_at if issue.created_at else datetime.datetime.min + issue.created_at + if issue.created_at + else datetime.datetime.min ) if issue_created_at.tzinfo is None: issue_created_at = issue_created_at.replace( @@ -569,9 +566,7 @@ def get_issues_without_assignee( if not issue.assignees: repo_unassigned_count += 1 except Exception as e: - _LOG.error( - "Error processing issue in '%s': %s", repo_name, e - ) + _LOG.error("Error processing issue in '%s': %s", repo_name, e) continue issues_per_repository[repo_name] = repo_unassigned_count issues_without_assignee += repo_unassigned_count @@ -630,11 +625,11 @@ def get_prs_by_person( username: str, org_name: str, period: Optional[Tuple[datetime.datetime, datetime.datetime]] = None, - state: str = "open", + state: str = "all", ) -> Dict[str, Any]: """ - Fetch the number of pull requests created by a specific GitHub user - in the given repositories and time period. + Fetch the number of pull requests created by a specific GitHub user in the + given repositories and time period. :param client: authenticated instance of the PyGithub client :param username: GitHub username to fetch pull request data for @@ -694,3 +689,587 @@ def get_prs_not_merged_by_person( "period": result["period"], "prs_per_repository": result["prs_per_repository"], } + + +def days_between( + period: Tuple[datetime.datetime, datetime.datetime], +) -> List[date]: + """ + Generate each date in time span. + + :param period: start and end datetime + :return: date span + """ + start_date = period[0].date() + end_date = period[1].date() + days: List[date] = [] + current = start_date + while current <= end_date: + days.append(current) + current += datetime.timedelta(days=1) + _LOG.info("Generated %d days in period.", len(days)) + return days + + +@hcacsimp.simple_cache(cache_type="json", write_through=True) +def get_commit_datetimes_by_repo_period_intrinsic( + client, + org: str, + repo: str, + username: Optional[str], + since: datetime.datetime, + until: datetime.datetime, +) -> List[str]: + """ + Fetch commit timestamps for user in repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param since: start datetime + :param until: end datetime + :return: commit timestamps in ISO format + """ + timestamps: List[str] = [] + try: + repo_obj = client.get_repo(f"{org}/{repo}") + # Grab all commits in range, then filter by author or committer. + for c in repo_obj.get_commits(since=since, until=until): + author_login = c.author.login if c.author else None + committer_login = c.committer.login if c.committer else None + if username in (author_login, committer_login): + dt = c.commit.author.date + dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) + timestamps.append(dt_utc.isoformat()) + _LOG.info( + "Fetched %d commits for %s/%s user=%s.", + len(timestamps), + org, + repo, + username, + ) + except Exception as e: + _LOG.warning( + "Failed to fetch commits for %s/%s user=%s: %s.", + org, + repo, + username, + e, + ) + return timestamps + + +@hcacsimp.simple_cache(cache_type="json", write_through=True) +def get_pr_datetimes_by_repo_period_intrinsic( + client, + org: str, + repo: str, + username: str, + since: datetime.datetime, + until: datetime.datetime, +) -> List[str]: + """ + Fetch pull request timestamps for user in repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param since: start datetime + :param until: end datetime + :return: PR created timestamps in ISO format + """ + timestamps: List[str] = [] + since_date = since.date().isoformat() + until_date = until.date().isoformat() + query = f"repo:{org}/{repo} is:pr author:{username} created:{since_date}..{until_date}" + try: + results = client.search_issues(query) + for issue in results: + dt = issue.created_at + dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) + timestamps.append(dt_utc.isoformat()) + _LOG.info( + "Found %d PRs for %s/%s user=%s.", + len(timestamps), + org, + repo, + username, + ) + except Exception as e: + _LOG.warning( + "PR search failed for %s/%s user=%s: %s.", org, repo, username, e + ) + return timestamps + + +@hcacsimp.simple_cache(cache_type="json", write_through=True) +def get_loc_stats_by_repo_period_intrinsic( + client, + org: str, + repo: str, + username: str, + since: datetime.datetime, + until: datetime.datetime, +) -> List[Dict[str, int]]: + """ + Fetch commit LOC stats for user in repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param since: start datetime + :param until: end datetime + :return: additions, deletions in code + """ + stats_list: List[Dict[str, int]] = [] + try: + repo_obj = client.get_repo(f"{org}/{repo}") + # Grab all commits in range, then filter by author/committer. + for c in repo_obj.get_commits(since=since, until=until): + author_login = c.author.login if c.author else None + committer_login = c.committer.login if c.committer else None + if username not in (author_login, committer_login): + continue + try: + s = c.stats + except Exception: + _LOG.warning("Could not fetch stats for commit %s.", c.sha) + continue + dt = c.commit.author.date + dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) + iso = dt_utc.date().isoformat() + stats_list.append( + {"date": iso, "additions": s.additions, "deletions": s.deletions} + ) + _LOG.info( + "Fetched LOC stats for %s/%s user=%s entries=%d.", + org, + repo, + username, + len(stats_list), + ) + except Exception as e: + _LOG.warning( + "Failed to fetch LOC for %s/%s user=%s: %s.", org, repo, username, e + ) + return stats_list + + +def build_daily_commit_df( + client, + org: str, + repo: str, + username: str, + period: Tuple[datetime.datetime, datetime.datetime], +) -> pd.DataFrame: + """ + Build daily commit counts for user and repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param period: start and end datetime objects + :return: data with date, commits, repo, user + """ + since, until = period + timestamps = get_commit_datetimes_by_repo_period_intrinsic( + client, org, repo, username, since, until + ) + df = pd.DataFrame({"ts": pd.to_datetime(timestamps)}) + df["date"] = df.ts.dt.date + daily = df.groupby("date").size().reset_index(name="commits") + all_days = pd.DataFrame({"date": days_between(period)}) + daily = all_days.merge(daily, on="date", how="left") + daily["commits"] = daily["commits"].fillna(0).astype(int) + daily["repo"] = repo + daily["user"] = username + _LOG.info("Built daily commit DataFrame rows=%d.", len(daily)) + return daily + + +def build_daily_pr_df( + client, + org: str, + repo: str, + username: str, + period: Tuple[datetime.datetime, datetime.datetime], +) -> pd.DataFrame: + """ + Build daily PR counts for user and repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param period: start and end datetime objects + :return: data with date, prs, repo, user + """ + since, until = period + timestamps = get_pr_datetimes_by_repo_period_intrinsic( + client, org, repo, username, since, until + ) + df = pd.DataFrame({"ts": pd.to_datetime(timestamps)}) + df["date"] = df.ts.dt.date + daily = df.groupby("date").size().reset_index(name="prs") + all_days = pd.DataFrame({"date": days_between(period)}) + daily = all_days.merge(daily, on="date", how="left") + daily["prs"] = daily["prs"].fillna(0).astype(int) + daily["repo"] = repo + daily["user"] = username + _LOG.info("Built daily PR DataFrame rows=%d.", len(daily)) + return daily + + +def build_daily_loc_df( + client, + org: str, + repo: str, + username: str, + period: Tuple[datetime.datetime, datetime.datetime], +) -> pd.DataFrame: + """ + Build daily LOC additions and deletions for user and repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param period: start and end datetime objects + :return: data with date, additions, deletions, repo, user + """ + since, until = period + # Fetch raw LOC stats list. + stats_list = get_loc_stats_by_repo_period_intrinsic( + client, org, repo, username, since, until + ) + # If no stats, return zeros for full range. + if not stats_list: + all_days = pd.DataFrame({"date": days_between(period)}) + # Initialize zeroes. + all_days["additions"] = all_days["date"].apply(lambda _: 0) + all_days["deletions"] = all_days["date"].apply(lambda _: 0) + # Format signs. + all_days["additions"] = ( + all_days["additions"].astype(str).apply(lambda x: "+" + x) + ) + all_days["deletions"] = ( + all_days["deletions"].astype(str).apply(lambda x: "-" + x) + ) + # Add context. + all_days["repo"] = repo + all_days["user"] = username + _LOG.info("Built daily LOC DataFrame rows=%d (no data).", len(all_days)) + return all_days + # Otherwise build from stats_list. + df = pd.DataFrame(stats_list) + df["date"] = pd.to_datetime(df["date"]).dt.date + # Sum per date. + daily = df.groupby("date")[["additions", "deletions"]].sum().reset_index() + # Ensure full date coverage. + all_days = pd.DataFrame({"date": days_between(period)}) + daily = all_days.merge(daily, on="date", how="left") + # Fill missing and integerize. + daily[["additions", "deletions"]] = ( + daily[["additions", "deletions"]].fillna(0).astype(int) + ) + # Apply sign formatting. + daily["additions"] = daily["additions"].astype(str).apply(lambda x: "+" + x) + daily["deletions"] = daily["deletions"].astype(str).apply(lambda x: "-" + x) + # Add context. + daily["repo"] = repo + daily["user"] = username + _LOG.info("Built daily LOC DataFrame rows=%d.", len(daily)) + return daily + + +def get_total_loc_for_period( + client, + org: str, + repo: str, + username: str, + period: Tuple[datetime.datetime, datetime.datetime], +) -> Dict[str, int]: + """ + Get total LOC additions and deletions for user and repo over period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repo: repository name + :param username: GitHub username + :param period: start and end datetime objects + :return: additions and deletions totals + """ + since, until = period + stats = get_loc_stats_by_repo_period_intrinsic( + client, org, repo, username, since, until + ) + total_add = sum(item["additions"] for item in stats) + total_del = sum(item["deletions"] for item in stats) + _LOG.info( + "Total LOC for %s/%s user=%s => +%d -%d.", + org, + repo, + username, + total_add, + total_del, + ) + return {"additions": total_add, "deletions": total_del} + + +def prefetch_periodic_user_repo_data( + client, + org: str, + repos: List[str], + users: List[str], + period: Tuple[datetime.datetime, datetime.datetime], +) -> None: + """ + Prefetch and cache commits, PRs, and LOC for each user and repo over + period. + + :param client: authenticated PyGithub client + :param org: GitHub org name + :param repos: list of repository names + :param users: list of GitHub usernames + :param period: start and end datetime objects + """ + # Validate org, repos, and users types. + if not isinstance(org, str): + raise ValueError(f"org must be a string, got {type(org).__name__}") + if not isinstance(repos, list) or not all(isinstance(r, str) for r in repos): + raise ValueError("repos must be a list of strings") + if not isinstance(users, list) or not all(isinstance(u, str) for u in users): + raise ValueError("users must be a list of strings") + start = time_module.time() + count = 0 + since, until = period + # Loop over each repo and user combination. + for repo in repos: + # Ensure each repo is string. + if not isinstance(repo, str): + raise ValueError(f"Expected repo to be a string but got {repo!r}") + _LOG.info("Starting prefetch for repo %s.", repo) + for user in users: + # Ensure each user is string. + if not isinstance(user, str): + raise ValueError(f"Expected user to be a string but got {user!r}") + get_commit_datetimes_by_repo_period_intrinsic( + client, org, repo, user, since, until + ) + get_pr_datetimes_by_repo_period_intrinsic( + client, org, repo, user, since, until + ) + get_loc_stats_by_repo_period_intrinsic( + client, org, repo, user, since, until + ) + count += 1 + elapsed = time_module.time() - start + _LOG.info( + "Prefetched %d user-repo combos in %.2f seconds for period %s to %s.", + count, + elapsed, + period[0], + period[1], + ) + + +def collect_all_metrics( + client, + org: str, + repos: List[str], + users: List[str], + period: Tuple[datetime.datetime, datetime.datetime], +) -> pd.DataFrame: + """ + Collect daily metrics for all user-repo combinations. + + :param client: authenticated PyGithub client + :param org: github org name + :param repos: repository names + :param users: github usernames + :param period: start and end datetime + :return: concatenated data with date, commits, prs, additions, + deletions, repo, user + """ + combined_frames: List[pd.DataFrame] = [] + for repo in repos: + # Ensure repo is a string. + if not isinstance(repo, str): + raise ValueError(f"Expected repo to be a string but got {repo!r}") + for user in users: + # Ensure user is a string. + if not isinstance(user, str): + raise ValueError(f"Expected user to be a string but got {user!r}") + # Build each metric DataFrame. + df_c = build_daily_commit_df(client, org, repo, user, period) + df_p = build_daily_pr_df(client, org, repo, user, period) + df_l = build_daily_loc_df(client, org, repo, user, period) + # Merge on date, repo, and user. + df = df_c.merge(df_p, on=["date", "repo", "user"], how="inner").merge( + df_l, on=["date", "repo", "user"], how="inner" + ) + combined_frames.append(df) + # Concatenate all DataFrames or return empty. + combined = ( + pd.concat(combined_frames, ignore_index=True) + if combined_frames + else pd.DataFrame() + ) + return combined + + +# Separate summary functions for user-repo and repo-user metrics for clarity. +def summarize_user_metrics_for_repo( + combined: pd.DataFrame, repo: str +) -> pd.DataFrame: + """ + Summarize total commits, PRs, and LOC per user in a specific repository. + + :param combined: data with all metrics + :param repo: repository name + :return: data with columns user, commits, prs, additions, deletions + """ + df = combined[combined["repo"] == repo].copy() + df["additions"] = df["additions"].str.replace("+", "").astype(int) + df["deletions"] = df["deletions"].str.replace("-", "").astype(int) + summary = ( + df.groupby("user") + .agg( + commits=pd.NamedAgg(column="commits", aggfunc="sum"), + prs=pd.NamedAgg(column="prs", aggfunc="sum"), + additions=pd.NamedAgg(column="additions", aggfunc="sum"), + deletions=pd.NamedAgg(column="deletions", aggfunc="sum"), + ) + .reset_index() + ) + return summary + + +def summarize_repo_metrics_for_user( + combined: pd.DataFrame, user: str +) -> pd.DataFrame: + """ + Summarize total commits, PRs, and LOC per repository for a specific user. + + :param combined: data with all metrics + :param user: GitHub username + :return: data with columns repo, commits, prs, additions, deletions + """ + df = combined[combined["user"] == user].copy() + df["additions"] = df["additions"].str.replace("+", "").astype(int) + df["deletions"] = df["deletions"].str.replace("-", "").astype(int) + summary = ( + df.groupby("repo") + .agg( + commits=pd.NamedAgg(column="commits", aggfunc="sum"), + prs=pd.NamedAgg(column="prs", aggfunc="sum"), + additions=pd.NamedAgg(column="additions", aggfunc="sum"), + deletions=pd.NamedAgg(column="deletions", aggfunc="sum"), + ) + .reset_index() + ) + return summary + + +def plot_metrics_by_user( + summary: pd.DataFrame, repo: str, metrics: Optional[List[str]] = None +) -> None: + """ + Plot specified metrics for users in a single repo as grouped bar chart. + + :param summary: data with summary from `compare_user_repo_summary` + :param repo: repository name + :param metrics: metrics to plot (commits, prs, additions, deletions) + """ + # Determine which metrics to plot. + available = ["commits", "prs", "additions", "deletions"] + to_plot = metrics if metrics else available + # Validate metrics. + for m in to_plot: + if m not in available: + raise ValueError(f"Unsupported metric '{m}'") + x = list(range(len(to_plot))) + n_users = len(summary) + width = 0.8 / n_users if n_users else 0.8 + fig, ax = plt.subplots() + # Plot bars and annotate counts. + for idx, user in enumerate(summary["user"]): + values = ( + summary.loc[summary["user"] == user, to_plot] + .astype(int) + .iloc[0] + .tolist() + ) + positions = [i + idx * width for i in x] + bars = ax.bar(positions, values, width=width, label=user) + for b in bars: + ax.text( + b.get_x() + b.get_width() / 2, + b.get_height(), + str(int(b.get_height())), + ha="center", + va="bottom", + ) + # Center tick labels under bar groups. + ax.set_xticks([i + width * (n_users - 1) / 2 for i in x]) + ax.set_xticklabels([m.capitalize() for m in to_plot]) + ax.set_ylabel("Count") + # Update title format per user request. + ax.set_title(f"Metric comparison for {repo} Repo") + ax.legend() + plt.tight_layout() + plt.show() + + +def plot_metrics_by_repo( + summary: pd.DataFrame, user: str, metrics: Optional[List[str]] = None +) -> None: + """ + Plot specified metrics for repos for a single user as grouped bar chart. + + :param summary: data with summary from `compare_user_across_repos_summary` + :param user: github username + :param metrics: metrics to plot (commits, prs, additions, deletions) + """ + # Determine which metrics to plot. + available = ["commits", "prs", "additions", "deletions"] + to_plot = metrics if metrics else available + # Validate metrics. + for m in to_plot: + if m not in available: + raise ValueError(f"Unsupported metric '{m}'") + x = list(range(len(to_plot))) + n_repos = len(summary) + width = 0.8 / n_repos if n_repos else 0.8 + fig, ax = plt.subplots() + # Plot bars and annotate counts. + for idx, repo in enumerate(summary["repo"]): + values = ( + summary.loc[summary["repo"] == repo, to_plot] + .astype(int) + .iloc[0] + .tolist() + ) + positions = [i + idx * width for i in x] + bars = ax.bar(positions, values, width=width, label=repo) + for b in bars: + ax.text( + b.get_x() + b.get_width() / 2, + b.get_height(), + str(int(b.get_height())), + ha="center", + va="bottom", + ) + # Center tick labels under bar groups. + ax.set_xticks([i + width * (n_repos - 1) / 2 for i in x]) + ax.set_xticklabels([m.capitalize() for m in to_plot]) + ax.set_ylabel("Count") + # Update title format per user request. + ax.set_title(f"Metric comparison for {user} across repos") + ax.legend() + plt.tight_layout() + plt.show() From 2387d69d1fa0524932f6542d49cb31da012371bc Mon Sep 17 00:00:00 2001 From: shaunak01 Date: Sat, 24 May 2025 23:09:18 +0000 Subject: [PATCH 3/8] Fix --- tutorial_github_causify_style/github_utils.py | 4 ++-- .../notebooks/github_utils_test.ipynb | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tutorial_github_causify_style/github_utils.py b/tutorial_github_causify_style/github_utils.py index c02a53b2ab..19c062a3da 100644 --- a/tutorial_github_causify_style/github_utils.py +++ b/tutorial_github_causify_style/github_utils.py @@ -132,8 +132,8 @@ def normalize_period_to_utc( Convert a datetime period to UTC and ensure both dates are timezone-aware. :param period: start and end datetime - :return: tuple of UTC-aware start and end datetime, or (None, None) - if period is None + :return: UTC-aware start and end datetime, or (None, None) if period + is None """ if not period: return None, None diff --git a/tutorial_github_causify_style/notebooks/github_utils_test.ipynb b/tutorial_github_causify_style/notebooks/github_utils_test.ipynb index 30e95897b0..bba214353a 100644 --- a/tutorial_github_causify_style/notebooks/github_utils_test.ipynb +++ b/tutorial_github_causify_style/notebooks/github_utils_test.ipynb @@ -6,7 +6,6 @@ "source": [ "CONTENTS:\n", "- [Github API to understand user Contribution](#github-api-to-understand-user-contribution)\n", - " - [These numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.](#these-numbers-come-straight-from-the-upstream-repo-via-the-rest-api,-so-they-only-include-commits-and-prs-where-you\u2019re-the-author-or-the-committer-on-that-repo.-they-**do-not**-pick-up-any-work-you-did-in-a-fork-(or-the-individual-commits-squashed-into-a-single-merge),-which-is-why-they\u2019ll-always-undercount-what-github-insights-shows-for-your-overall-contributions.)\n", " - [Set your Github PAT](#set-your-github-pat)\n", " - [Pre-feth all the data you need in cache](#pre-feth-all-the-data-you-need-in-cache)\n", " - [Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period](#query-extraction-takes-time,-so-prefetch-all-data-in-cache-for-all-the-users,-repos-and-time-frames-you-need.-once-in-cache-there-are-several-utility-functions-to-help-understand-the-user-contribution.-following-is-the-data-we-will-fetch-for-users-in-multiple-repos-for-the-given-period)\n", @@ -30,8 +29,7 @@ "id": "923ef379-8424-46df-9b60-29d35a63a331", "metadata": {}, "source": [ - "\n", - "### These numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.\n" + "The numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.\n" ] }, { From bd90dfd9f8689375347f6d4d857a02c579553f1f Mon Sep 17 00:00:00 2001 From: GP Saggese Date: Tue, 27 May 2025 17:19:50 -0400 Subject: [PATCH 4/8] AI review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-commit checks: All checks passed ✅ --- helpers_root | 2 +- tutorial_github_causify_style/github_utils.py | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/helpers_root b/helpers_root index 69a00d2f8d..0387ed7fa9 160000 --- a/helpers_root +++ b/helpers_root @@ -1 +1 @@ -Subproject commit 69a00d2f8dd0d4de1aa8893d7539de91538377b9 +Subproject commit 0387ed7fa93653b9ca98396fb3580a7fa7a19ba3 diff --git a/tutorial_github_causify_style/github_utils.py b/tutorial_github_causify_style/github_utils.py index 19c062a3da..723ba4ddc6 100644 --- a/tutorial_github_causify_style/github_utils.py +++ b/tutorial_github_causify_style/github_utils.py @@ -84,6 +84,7 @@ def get_repo_names(client: github.Github, org_name: str) -> Dict[str, List[str]] - owner: name of the organization - repositories: repository names """ + # TODO: Turn the try-except into an assertion. No point in trying to recover. try: # Attempt to get the organization. owner = client.get_organization(org_name) @@ -135,6 +136,7 @@ def normalize_period_to_utc( :return: UTC-aware start and end datetime, or (None, None) if period is None """ + # TODO: Code implementation-137: Use `if period is None` instead of `if not period` to check if `period` is `None`. if not period: return None, None return tuple( @@ -216,7 +218,6 @@ def get_total_commits( "period": f"{since} to {until}" if since and until else "All time", "commits_per_repository": commits_per_repository, } - return result @@ -612,6 +613,7 @@ def get_commits_by_person( result = get_total_commits( client=client, org_name=org_name, usernames=[username], period=period ) + # TODO: Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. return { "user": username, "total_commits": result["total_commits"], @@ -651,6 +653,7 @@ def get_prs_by_person( period=period, state=state, ) + # Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. return { "user": username, "total_prs": result["total_prs"], @@ -683,6 +686,7 @@ def get_prs_not_merged_by_person( result = get_prs_not_merged( client=client, org_name=org_name, usernames=[username], period=period ) + # Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. return { "user": username, "prs_not_merged": result["prs_not_merged"], @@ -707,6 +711,7 @@ def days_between( while current <= end_date: days.append(current) current += datetime.timedelta(days=1) + # Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. _LOG.info("Generated %d days in period.", len(days)) return days @@ -962,6 +967,7 @@ def build_daily_loc_df( # Add context. all_days["repo"] = repo all_days["user"] = username + # TODO: Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. _LOG.info("Built daily LOC DataFrame rows=%d (no data).", len(all_days)) return all_days # Otherwise build from stats_list. @@ -982,6 +988,7 @@ def build_daily_loc_df( # Add context. daily["repo"] = repo daily["user"] = username + # TODO: Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. _LOG.info("Built daily LOC DataFrame rows=%d.", len(daily)) return daily From 41ebd95291220a552041fe0c9313822bcdbd4f3e Mon Sep 17 00:00:00 2001 From: GP Saggese Date: Tue, 27 May 2025 17:31:20 -0400 Subject: [PATCH 5/8] AI review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-commit checks: All checks passed ✅ --- tutorial_github_causify_style/github_utils.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tutorial_github_causify_style/github_utils.py b/tutorial_github_causify_style/github_utils.py index 723ba4ddc6..3ba1af34b1 100644 --- a/tutorial_github_causify_style/github_utils.py +++ b/tutorial_github_causify_style/github_utils.py @@ -8,6 +8,7 @@ import logging import os import time as time_module +# TODO: Imports-72: Avoid using `from ... import ...` unless it is the `typing` package. from datetime import date, timezone from typing import Any, Dict, List, Optional, Tuple @@ -613,7 +614,7 @@ def get_commits_by_person( result = get_total_commits( client=client, org_name=org_name, usernames=[username], period=period ) - # TODO: Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. + # TODO(False): Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. return { "user": username, "total_commits": result["total_commits"], @@ -653,7 +654,7 @@ def get_prs_by_person( period=period, state=state, ) - # Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. + # TODO(False): Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. return { "user": username, "total_prs": result["total_prs"], @@ -686,7 +687,7 @@ def get_prs_not_merged_by_person( result = get_prs_not_merged( client=client, org_name=org_name, usernames=[username], period=period ) - # Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. + # TODO(False): Functions-224: Do not put computations of the output in the `return` line. Compute the output first, assign it to a variable, and then return this variable. return { "user": username, "prs_not_merged": result["prs_not_merged"], @@ -711,7 +712,7 @@ def days_between( while current <= end_date: days.append(current) current += datetime.timedelta(days=1) - # Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. + # TODO(False): Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. _LOG.info("Generated %d days in period.", len(days)) return days @@ -967,7 +968,7 @@ def build_daily_loc_df( # Add context. all_days["repo"] = repo all_days["user"] = username - # TODO: Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. + # TODO(False): Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. _LOG.info("Built daily LOC DataFrame rows=%d (no data).", len(all_days)) return all_days # Otherwise build from stats_list. @@ -988,7 +989,7 @@ def build_daily_loc_df( # Add context. daily["repo"] = repo daily["user"] = username - # TODO: Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. + # TODO(False): Logging-248: Use `_LOG.debug()` instead of `_LOG.info()` for tracing execution. _LOG.info("Built daily LOC DataFrame rows=%d.", len(daily)) return daily From aa95d290233f422161602d4c91152a604e1badf8 Mon Sep 17 00:00:00 2001 From: shaunak01 Date: Wed, 28 May 2025 17:01:51 +0000 Subject: [PATCH 6/8] Fix --- tutorial_github_causify_style/github_utils.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tutorial_github_causify_style/github_utils.py b/tutorial_github_causify_style/github_utils.py index 19c062a3da..bcf518f73b 100644 --- a/tutorial_github_causify_style/github_utils.py +++ b/tutorial_github_causify_style/github_utils.py @@ -7,8 +7,7 @@ import datetime import logging import os -import time as time_module -from datetime import date, timezone +import time from typing import Any, Dict, List, Optional, Tuple import github @@ -27,8 +26,7 @@ class GitHubAPI: """ - A class to initialize and manage authentication with the GitHub API using - PyGithub. + Initialize and manage authentication with the GitHub API using PyGithub. """ def __init__( @@ -693,16 +691,16 @@ def get_prs_not_merged_by_person( def days_between( period: Tuple[datetime.datetime, datetime.datetime], -) -> List[date]: +) -> List[datetime.date]: """ Generate each date in time span. :param period: start and end datetime :return: date span """ - start_date = period[0].date() - end_date = period[1].date() - days: List[date] = [] + start_date = period[0].datetime.date() + end_date = period[1].datetime.date() + days: List[datetime.date] = [] current = start_date while current <= end_date: days.append(current) @@ -740,7 +738,9 @@ def get_commit_datetimes_by_repo_period_intrinsic( committer_login = c.committer.login if c.committer else None if username in (author_login, committer_login): dt = c.commit.author.date - dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) + dt_utc = ( + dt if dt.tzinfo else dt.replace(tzinfo=datetime.timezone.utc) + ) timestamps.append(dt_utc.isoformat()) _LOG.info( "Fetched %d commits for %s/%s user=%s.", @@ -781,14 +781,14 @@ def get_pr_datetimes_by_repo_period_intrinsic( :return: PR created timestamps in ISO format """ timestamps: List[str] = [] - since_date = since.date().isoformat() - until_date = until.date().isoformat() + since_date = since.datetime.date().isoformat() + until_date = until.datetime.date().isoformat() query = f"repo:{org}/{repo} is:pr author:{username} created:{since_date}..{until_date}" try: results = client.search_issues(query) for issue in results: dt = issue.created_at - dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) + dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=datetime.timezone.utc) timestamps.append(dt_utc.isoformat()) _LOG.info( "Found %d PRs for %s/%s user=%s.", @@ -839,8 +839,8 @@ def get_loc_stats_by_repo_period_intrinsic( _LOG.warning("Could not fetch stats for commit %s.", c.sha) continue dt = c.commit.author.date - dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc) - iso = dt_utc.date().isoformat() + dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=datetime.timezone.utc) + iso = dt_utc.datetime.date().isoformat() stats_list.append( {"date": iso, "additions": s.additions, "deletions": s.deletions} ) @@ -1044,7 +1044,7 @@ def prefetch_periodic_user_repo_data( raise ValueError("repos must be a list of strings") if not isinstance(users, list) or not all(isinstance(u, str) for u in users): raise ValueError("users must be a list of strings") - start = time_module.time() + start = time.time() count = 0 since, until = period # Loop over each repo and user combination. @@ -1067,7 +1067,7 @@ def prefetch_periodic_user_repo_data( client, org, repo, user, since, until ) count += 1 - elapsed = time_module.time() - start + elapsed = time.time() - start _LOG.info( "Prefetched %d user-repo combos in %.2f seconds for period %s to %s.", count, From 6c2ae77698e7bcedd1993c521a50aefcb5dfd3c7 Mon Sep 17 00:00:00 2001 From: shaunak01 Date: Thu, 29 May 2025 16:27:49 +0000 Subject: [PATCH 7/8] Checkpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-commit checks: All checks passed ✅ --- tutorial_github_causify_style/github_utils.py | 10 +- .../github_utils_test.ipynb | 688 ++++++++++++++++++ .../notebooks/github_utils_test.ipynb | 677 ----------------- 3 files changed, 693 insertions(+), 682 deletions(-) create mode 100644 tutorial_github_causify_style/github_utils_test.ipynb delete mode 100644 tutorial_github_causify_style/notebooks/github_utils_test.ipynb diff --git a/tutorial_github_causify_style/github_utils.py b/tutorial_github_causify_style/github_utils.py index d23fb1ce10..bc2b85f4dc 100644 --- a/tutorial_github_causify_style/github_utils.py +++ b/tutorial_github_causify_style/github_utils.py @@ -702,8 +702,8 @@ def days_between( :param period: start and end datetime :return: date span """ - start_date = period[0].datetime.date() - end_date = period[1].datetime.date() + start_date = period[0].date() + end_date = period[1].date() days: List[datetime.date] = [] current = start_date while current <= end_date: @@ -786,8 +786,8 @@ def get_pr_datetimes_by_repo_period_intrinsic( :return: PR created timestamps in ISO format """ timestamps: List[str] = [] - since_date = since.datetime.date().isoformat() - until_date = until.datetime.date().isoformat() + since_date = since.date().isoformat() + until_date = until.date().isoformat() query = f"repo:{org}/{repo} is:pr author:{username} created:{since_date}..{until_date}" try: results = client.search_issues(query) @@ -845,7 +845,7 @@ def get_loc_stats_by_repo_period_intrinsic( continue dt = c.commit.author.date dt_utc = dt if dt.tzinfo else dt.replace(tzinfo=datetime.timezone.utc) - iso = dt_utc.datetime.date().isoformat() + iso = dt_utc.date().isoformat() stats_list.append( {"date": iso, "additions": s.additions, "deletions": s.deletions} ) diff --git a/tutorial_github_causify_style/github_utils_test.ipynb b/tutorial_github_causify_style/github_utils_test.ipynb new file mode 100644 index 0000000000..744cc7f8be --- /dev/null +++ b/tutorial_github_causify_style/github_utils_test.ipynb @@ -0,0 +1,688 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "CONTENTS:\n", + "- [Github API to understand user Contribution](#github-api-to-understand-user-contribution)\n", + " - [These numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.](#these-numbers-come-straight-from-the-upstream-repo-via-the-rest-api,-so-they-only-include-commits-and-prs-where-you\u2019re-the-author-or-the-committer-on-that-repo.-they-**do-not**-pick-up-any-work-you-did-in-a-fork-(or-the-individual-commits-squashed-into-a-single-merge),-which-is-why-they\u2019ll-always-undercount-what-github-insights-shows-for-your-overall-contributions.)\n", + " - [Set your Github PAT](#set-your-github-pat)\n", + " - [Pre-feth all the data you need in cache](#pre-feth-all-the-data-you-need-in-cache)\n", + " - [Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period](#query-extraction-takes-time,-so-prefetch-all-data-in-cache-for-all-the-users,-repos-and-time-frames-you-need.-once-in-cache-there-are-several-utility-functions-to-help-understand-the-user-contribution.-following-is-the-data-we-will-fetch-for-users-in-multiple-repos-for-the-given-period)\n", + " - [Combine the data for statistics and visualizations](#combine-the-data-for-statistics-and-visualizations)\n", + " - [Compare users on a repo based on `commits`, `prs`, `additions` and `deletions`](#compare-users-on-a-repo-based-on-`commits`,-`prs`,-`additions`-and-`deletions`)\n", + " - [See stats of a user on multiple repos based on `commits`, `prs`, `additions` and `deletions`](#see-stats-of-a-user-on-multiple-repos-based-on-`commits`,-`prs`,-`additions`-and-`deletions`)\n", + " - [There are many more helper funcs to see and compare statistics. Look at github_utils for more info -> `tutorial_github_causify_style/github_utils.py`](#there-are-many-more-helper-funcs-to-see-and-compare-statistics.-look-at-github_utils-for-more-info-->-`tutorial_github_causify_style/github_utils.py`)" + ] + }, + { + "cell_type": "markdown", + "id": "8bdfbc31-a6d6-431e-b0ed-bdc69b8eec25", + "metadata": {}, + "source": [ + "\n", + "# Github API to understand user Contribution" + ] + }, + { + "cell_type": "markdown", + "id": "923ef379-8424-46df-9b60-29d35a63a331", + "metadata": {}, + "source": [ + "\n", + "### These numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "442cd592-3137-4d73-a113-655bf8dfd3fe", + "metadata": {}, + "outputs": [], + "source": [ + "!sudo /bin/bash -c \"(source /venv/bin/activate; pip install --quiet jupyterlab-vim PyGithub)\"\n", + "!jupyter labextension enable" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "268ddc35-9bb4-4e0a-b7f4-a8409baf9904", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "import os\n", + "import datetime\n", + "import time\n", + "import importlib \n", + "\n", + "import github_utils\n", + "import helpers.hcache_simple as hcache\n", + "import helpers.hcache_simple as hcacsimp\n", + "from github import Github\n", + "\n", + "# Enable logging.\n", + "logging.basicConfig(level=logging.INFO)\n", + "_LOG = logging.getLogger(__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "9c25ee1d-620b-485e-b98c-769c7fff8ab4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "importlib.reload(github_utils)" + ] + }, + { + "cell_type": "markdown", + "id": "6afd498b-8453-42e1-852c-ac093f8e0bfd", + "metadata": {}, + "source": [ + "\n", + "## Set your Github PAT" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "3220998c-1261-418f-859b-b20bb9a6cb61", + "metadata": {}, + "outputs": [], + "source": [ + "# Set your GitHub access token here.\n", + "os.environ[\"GITHUB_ACCESS_TOKEN\"] = \"YOUR_GIT_PAT\"" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "03983a64-78a2-49c3-9163-815cf0ef3a77", + "metadata": {}, + "outputs": [], + "source": [ + "access_token = os.getenv(\"GITHUB_ACCESS_TOKEN\")\n", + "if not access_token:\n", + " _LOG.error(\"GITHUB_ACCESS_TOKEN not set. Exiting.\")\n", + " raise ValueError(\"Set GITHUB_ACCESS_TOKEN environment variable\")\n", + "\n", + "client = github_utils.GitHubAPI(access_token=access_token).get_client()" + ] + }, + { + "cell_type": "markdown", + "id": "4cc7efd4-af91-44e8-9e3c-2bdbc8440c9d", + "metadata": {}, + "source": [ + "\n", + "## Pre-feth all the data you need in cache " + ] + }, + { + "cell_type": "markdown", + "id": "a7772ca8-b716-412a-8526-74977f0c3ae5", + "metadata": {}, + "source": [ + "\n", + "### Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period \n", + "- Prs opened in the repo\n", + "- Commits done\n", + "- LOC [additions and deletions]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "0002b5e0-6975-4058-b9cd-b06676c89d38", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:github_utils:Starting prefetch for repo helpers.\n", + "INFO:github_utils:Fetched 20 commits for causify-ai/helpers user=Shaunak01.\n", + "INFO:github_utils:Found 24 PRs for causify-ai/helpers user=Shaunak01.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/helpers user=Shaunak01 entries=20.\n", + "INFO:github_utils:Starting prefetch for repo tutorials.\n", + "INFO:github_utils:Fetched 1 commits for causify-ai/tutorials user=Shaunak01.\n", + "INFO:github_utils:Found 3 PRs for causify-ai/tutorials user=Shaunak01.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/tutorials user=Shaunak01 entries=1.\n", + "INFO:github_utils:Starting prefetch for repo cmamp.\n", + "INFO:github_utils:Fetched 23 commits for causify-ai/cmamp user=Shaunak01.\n", + "INFO:github_utils:Found 28 PRs for causify-ai/cmamp user=Shaunak01.\n", + "INFO:github_utils:Fetched LOC stats for causify-ai/cmamp user=Shaunak01 entries=23.\n", + "INFO:github_utils:Prefetched 9 user-repo combos in 62.79 seconds for period 2025-01-01 00:00:00+00:00 to 2025-05-24 00:00:00+00:00.\n" + ] + } + ], + "source": [ + "github_utils.prefetch_periodic_user_repo_data(\n", + " client,\n", + " org=\"causify-ai\",\n", + " repos=[\"helpers\",\"tutorials\",\"cmamp\"],\n", + " users=[\"tkpratardan\",\"Prahar08modi\",\"Shaunak01\"],\n", + " period=(\n", + " datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc),\n", + " datetime.datetime(2025, 5, 24, tzinfo=datetime.timezone.utc),\n", + " ),\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "4e6e1277-32f0-4fca-9c62-6f29eebb6a44", + "metadata": {}, + "source": [ + "\n", + "## Combine the data for statistics and visualizations" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "d03e07fc-37f6-4d69-8c16-2bc4296d0334", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144 (no data).\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144 (no data).\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily PR DataFrame rows=144.\n", + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily LOC DataFrame rows=144.\n" + ] + } + ], + "source": [ + "combined = github_utils.collect_all_metrics(\n", + " client, org=\"causify-ai\",\n", + " repos=[\"helpers\",\"tutorials\",\"cmamp\"],\n", + " users=[\"Prahar08modi\",\"tkpratardan\",\"Shaunak01\"],\n", + " period=(datetime.datetime(2025,1,1, tzinfo=datetime.timezone.utc),\n", + " datetime.datetime(2025,5,24, tzinfo=datetime.timezone.utc)),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "eb0aa61c-60f4-4b85-841a-623e3d069913", + "metadata": {}, + "source": [ + "\n", + "## Compare users on a repo based on `commits`, `prs`, `additions` and `deletions`" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "62bfd155-8e08-4ddb-82a2-3ec9d9a2c9ca", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnYAAAHWCAYAAAD6oMSKAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUepJREFUeJzt3XlYVOX///HXgLIomwuLFgooLriHSqjlEopLppZpZh/XzK9ralZaLpiVlbmVpp/65tLikqVmZpiSWblvlOaSmogbrgHiAgbn90c/5usEKCgycHw+rmuuy3POfd/nfWYme3mWeyyGYRgCAABAkedg7wIAAACQPwh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2QCE3f/58WSwWxcXF2buUIq2wv49nzpxR586dVaZMGVksFk2fPt3eJdlVVFSULBbLbfVt1qyZmjVrlr8FAUUEwQ74/zL/x2+xWPTLL79k2W4Yhvz9/WWxWPToo4/e1j4++OADzZ8//w4rhRkNHz5ca9as0ejRo/Xpp5+qdevWd21fV65cUVRUlH788Ue7jlHYxcXFWf9OsFgscnBwUOnSpdWmTRtt3rzZ3uUB2SLYAf/i4uKihQsXZlm/YcMGnThxQs7Ozrc99u0Eu//85z+6evWqKlaseNv7ReF/H3/44Qd16NBBI0eO1DPPPKNq1ardtX1duXJFEyZMuONgd6dj3MyYMWN09erVuzJ2XnXr1k2ffvqp5s2bpwEDBmjLli1q3ry59uzZY+/SgCwIdsC/tG3bVkuXLtXff/9ts37hwoUKDQ2Vn59fgdRx+fJlSZKjo6NcXFxu+7LUva6ovI9nz56Vl5dXvo137do1ZWRk5Nt4BSXz8ypWrJhcXFzsXM0/HnjgAT3zzDPq2bOn3njjDS1atEipqamaPXu2vUsDsiDYAf/SrVs3XbhwQWvXrrWuS0tL05dffqmnn3462z4ZGRmaPn26atSoIRcXF/n6+qp///7666+/rG0CAgL0+++/a8OGDdZLO5n3AWVeBt6wYYMGDhwoHx8f3X///Tbb/n1v2HfffaemTZvK3d1dHh4eatCgQbZnGv/t5MmT6tu3r8qXLy9nZ2cFBgZqwIABSktLs7b5888/9eSTT6p06dIqUaKEHnzwQX377bc24/z444+yWCz64osvNGHCBN13331yd3dX586dlZSUpNTUVA0bNkw+Pj5yc3NT7969lZqaajOGxWLR4MGD9fnnn6tq1apycXFRaGiofvrpJ5t2x44d08CBA1W1alW5urqqTJkyevLJJ7O8J3l9H3fs2KHIyEiVLVtWrq6uCgwMVJ8+fWzGvHz5sl544QX5+/vL2dlZVatW1bvvvivDMLI9lhUrVqhmzZpydnZWjRo1FB0dfdPPI7MuwzA0a9Ys63fjdj6LxYsXa8yYMbrvvvtUokQJJScnZ9lfXFycvL29JUkTJkyw7i8qKkpSzven9erVSwEBAbkaQ/rnDORDDz2kkiVLysvLSx06dND+/fttxsy8j27fvn16+umnVapUKTVp0sRm243mzZunFi1ayMfHR87OzgoJCcl1uHr//fdVo0YNlShRQqVKlVL9+vVz9d9Ldh566CFJ0pEjR2zWJyYmatiwYdbvSuXKlfX222/bBOzMy7vvvvuupk2bpooVK8rV1VVNmzbV3r17s+wrN+8jcKNi9i4AKGwCAgIUHh6uRYsWqU2bNpL+CVFJSUl66qmn9N5772Xp079/f82fP1+9e/fW0KFDdfToUc2cOVO7d+/Wxo0bVbx4cU2fPl1DhgyRm5ubXn31VUmSr6+vzTgDBw6Ut7e3xo0bZz1zkZ358+erT58+qlGjhkaPHi0vLy/t3r1b0dHROYZPSTp16pQaNmyoxMREPffcc6pWrZpOnjypL7/8UleuXJGTk5POnDmjRo0a6cqVKxo6dKjKlCmjBQsW6LHHHtOXX36pTp062Yw5adIkubq6atSoUTp8+LDef/99FS9eXA4ODvrrr78UFRWlLVu2aP78+QoMDNS4ceNs+m/YsEFLlizR0KFD5ezsrA8++ECtW7fWtm3bVLNmTUnS9u3btWnTJj311FO6//77FRcXp9mzZ6tZs2bat2+fSpQokef38ezZs2rVqpW8vb01atQoeXl5KS4uTsuWLbO2MQxDjz32mNavX6++ffuqbt26WrNmjV588UWdPHlS06ZNsxnzl19+0bJlyzRw4EC5u7vrvffe0xNPPKH4+HiVKVMm2zoefvhhffrpp/rPf/6jli1bqkePHtZtef0sJk6cKCcnJ40cOVKpqalycnLKsj9vb2/Nnj1bAwYMUKdOnfT4449LkmrXrp1tfdm51Rjr1q1TmzZtFBQUpKioKF29elXvv/++GjdurF27dlkDYqYnn3xSwcHBevPNN7ME5hvNnj1bNWrU0GOPPaZixYrpm2++0cCBA5WRkaFBgwbl2O+jjz7S0KFD1blzZz3//PO6du2afvvtN23duvWm/73kJPMfB6VKlbKuu3Llipo2baqTJ0+qf//+qlChgjZt2qTRo0fr9OnTWR6G+eSTT3Tp0iUNGjRI165d04wZM9SiRQvt2bPH+vdCXt9HQJJkADAMwzDmzZtnSDK2b99uzJw503B3dzeuXLliGIZhPPnkk0bz5s0NwzCMihUrGu3atbP2+/nnnw1Jxueff24zXnR0dJb1NWrUMJo2bZrjvps0aWL8/fff2W47evSoYRiGkZiYaLi7uxthYWHG1atXbdpmZGTc9Bh79OhhODg4GNu3b8+yLbPvsGHDDEnGzz//bN126dIlIzAw0AgICDDS09MNwzCM9evXG5KMmjVrGmlpada23bp1MywWi9GmTRub8cPDw42KFSvarJNkSDJ27NhhXXfs2DHDxcXF6NSpk3Vd5udwo82bNxuSjE8++cS6Li/v4/Lly62fd05WrFhhSDJef/11m/WdO3c2LBaLcfjwYZtjcXJysln366+/GpKM999/P8d93Nh/0KBBNuvy+lkEBQVl+17927lz5wxJxvjx47Nsa9q0abbf0Z49e9p8fjcbo27duoaPj49x4cIF67pff/3VcHBwMHr06GFdN378eEOS0a1btyxjZG67UXbHFhkZaQQFBd30GDp06GDUqFEjS99bOXr0qCHJmDBhgnHu3DkjISHB+Pnnn40GDRoYkoylS5da206cONEoWbKk8ccff9iMMWrUKMPR0dGIj4+3GdPV1dU4ceKEtd3WrVsNScbw4cOt63L7PgI34lIskI0uXbro6tWrWrVqlS5duqRVq1bl+C/7pUuXytPTUy1bttT58+etr9DQULm5uWn9+vW53m+/fv3k6Oh40zZr167VpUuXNGrUqCz3IN3s/rGMjAytWLFC7du3V/369bNsz+y7evVqNWzY0HpJTJLc3Nz03HPPKS4uTvv27bPp16NHDxUvXty6HBYWJsMwslzSDAsL0/Hjx7PcuxgeHq7Q0FDrcoUKFdShQwetWbNG6enpkiRXV1fr9uvXr+vChQuqXLmyvLy8tGvXrizHkpv3MfN+tlWrVun69evZtlm9erUcHR01dOhQm/UvvPCCDMPQd999Z7M+IiJClSpVsi7Xrl1bHh4e+vPPP29aS07y+ln07NnT5r2yh9OnTys2Nla9evVS6dKlretr166tli1bavXq1Vn6/M///E+uxr7x2JKSknT+/Hk1bdpUf/75p5KSknLs5+XlpRMnTmj79u15OJL/M378eHl7e8vPz08PPfSQ9u/frylTpqhz587WNkuXLtVDDz2kUqVK2fw9EBERofT09Cy3F3Ts2FH33Xefdblhw4YKCwuzvj+38z4CEvfYAdny9vZWRESEFi5cqGXLlik9Pd3mL/EbHTp0SElJSfLx8ZG3t7fNKyUlRWfPns31fgMDA2/ZJvO+nszLlLl17tw5JScn37LfsWPHVLVq1Szrq1evbt1+owoVKtgse3p6SpL8/f2zrM/IyMjyP+Dg4OAs+6pSpYquXLmic+fOSZKuXr2qcePGWe9dKlu2rLy9vZWYmJjt/9Bz8z42bdpUTzzxhCZMmKCyZcuqQ4cOmjdvns19gMeOHVP58uXl7u5u0ze374X0z+W6G++1zIu8fha5Oe67LbOmnOo+f/58lsvjua1748aNioiIsN5v5u3trVdeeUWSbhrsXn75Zbm5ualhw4YKDg7WoEGDtHHjxtwekp577jmtXbtW33zzjYYPH66rV69a/9GR6dChQ4qOjs7yd0BERIQkZfl7IKfvfeZl3tt5HwGJe+yAHD399NPq16+fEhIS1KZNmxyfWMzIyJCPj48+//zzbLdn3mSeG/Y+23I7cjozltN64yb3UOVkyJAhmjdvnoYNG6bw8HB5enrKYrHoqaeeyvbJz9y8jxaLRV9++aW2bNmib775RmvWrFGfPn00ZcoUbdmyRW5ubnmuMz+P+Xbkx/cn80GOf/t3kMlPuan7yJEjeuSRR1StWjVNnTpV/v7+cnJy0urVqzVt2rSbPgFcvXp1HTx4UKtWrVJ0dLS++uorffDBBxo3bpwmTJhwy30HBwdbA9qjjz4qR0dHjRo1Ss2bN7ee/c7IyFDLli310ksvZTtGlSpVbrkfID8Q7IAcdOrUSf3799eWLVu0ZMmSHNtVqlRJ69atU+PGjW/5P6j8mGoj81Lf3r17Vbly5Vz38/b2loeHR7ZP3t2oYsWKOnjwYJb1Bw4csG7PT4cOHcqy7o8//lCJEiWsofjLL79Uz549NWXKFGuba9euKTEx8Y73/+CDD+rBBx/UG2+8oYULF6p79+5avHixnn32WVWsWFHr1q3TpUuXbM7a3a334t/u1mdxs+9hqVKlsr10/O+zgzmNkVlTTnWXLVtWJUuWzEu5kqRvvvlGqampWrlypc2Z0dze6lCyZEl17dpVXbt2VVpamh5//HG98cYbGj16dJ6nVXn11Vf10UcfacyYMdannitVqqSUlBRrALyVnL73mQ9E3K33EebHpVggB25ubpo9e7aioqLUvn37HNt16dJF6enpmjhxYpZtf//9t034KFmy5B2HkVatWsnd3V2TJk3StWvXbLbd7MyQg4ODOnbsqG+++UY7duzIsj2zb9u2bbVt2zabmfUvX76sDz/8UAEBAQoJCbmj+v9t8+bNNvfJHT9+XF9//bVatWplPQPm6OiY5djef//9OzqL9Ndff2UZs27dupJkvRzbtm1bpaena+bMmTbtpk2bJovFYn1q+m65W59F5lPE2X0XK1WqpAMHDlgvg0vSr7/+muXSZU5jlCtXTnXr1tWCBQtstu3du1fff/+92rZte1s1Z34XbvzMkpKSNG/evFv2vXDhgs2yk5OTQkJCZBhGjvdX3oyXl5f69++vNWvWKDY2VtI/fw9s3rxZa9asydI+MTExy72lK1as0MmTJ63L27Zt09atW63fqbv1PsL8OGMH3ETPnj1v2aZp06bq37+/Jk2apNjYWLVq1UrFixfXoUOHtHTpUs2YMcN6f15oaKhmz56t119/XZUrV5aPj49atGiRp5o8PDw0bdo0Pfvss2rQoIF1/q9ff/1VV65c0YIFC3Ls++abb+r7779X06ZN9dxzz6l69eo6ffq0li5dql9++UVeXl4aNWqUdaqXoUOHqnTp0lqwYIGOHj2qr776Sg4O+fvvwZo1ayoyMtJmuhNJNpfIHn30UX366afy9PRUSEiINm/erHXr1uU4hUhuLFiwQB988IE6deqkSpUq6dKlS/roo4/k4eFh/Z9m+/bt1bx5c7366quKi4tTnTp19P333+vrr7/WsGHDbB6UuBvu1mfh6uqqkJAQLVmyRFWqVFHp0qVVs2ZN1axZU3369NHUqVMVGRmpvn376uzZs5ozZ45q1KhhMy/ezcaYPHmy2rRpo/DwcPXt29c6TYenp6fNXHd50apVKzk5Oal9+/bq37+/UlJS9NFHH8nHx0enT5++ZV8/Pz81btxYvr6+2r9/v2bOnKl27dpluX8yt55//nlNnz5db731lhYvXqwXX3xRK1eu1KOPPqpevXopNDRUly9f1p49e/Tll18qLi5OZcuWtfavXLmymjRpogEDBig1NVXTp09XmTJlbC7l3o33EfcAOz2NCxQ6N053cjP/nu4k04cffmiEhoYarq6uhru7u1GrVi3jpZdeMk6dOmVtk5CQYLRr185wd3c3JFmnZLjZvv89TUemlStXGo0aNTJcXV0NDw8Po2HDhsaiRYtueZzHjh0zevToYXh7exvOzs5GUFCQMWjQICM1NdXa5siRI0bnzp0NLy8vw8XFxWjYsKGxatUqm3Eyp9i4ccqHmx1L5vQV586ds67T/5/i47PPPjOCg4MNZ2dno169esb69ett+v71119G7969jbJlyxpubm5GZGSkceDAAaNixYpGz549b7nv7N7HXbt2Gd26dTMqVKhgODs7Gz4+Psajjz5qM/WKYfwzvcjw4cON8uXLG8WLFzeCg4ONyZMnZ5laRtlMV2IYRpYac5JT/zv5LG5m06ZNRmhoqOHk5JRl2pLPPvvMCAoKMpycnIy6desaa9asyTLdya3GWLdundG4cWPr97N9+/bGvn37bPpn953497YbrVy50qhdu7bh4uJiBAQEGG+//bYxd+7cLP99/Hu6k//+97/Gww8/bJQpU8ZwdnY2KlWqZLz44otGUlLSTd+jzKlJJk+enO32Xr16GY6OjtYpbi5dumSMHj3aqFy5suHk5GSULVvWaNSokfHuu+9apwS6ccwpU6YY/v7+hrOzs/HQQw8Zv/76a5Z95OZ9BG5kMYwCuqsXAP7FYrFo0KBBWS51AmYVFxenwMBATZ48WSNHjrR3OTAh7rEDAAAwCYIdAACASRDsAAAATIJ77AAAAEyCM3YAAAAmQbADAAAwCSYozkZGRoZOnTold3f3fPkJKAAAgNtlGIYuXbqk8uXL33JicoJdNk6dOiV/f397lwEAAGB1/Phx3X///TdtQ7DLRuZPzBw/flweHh52rgYAANzLkpOT5e/vn6ufwCPYZSPz8quHhwfBDgAAFAq5uT2MhycAAABMgmAHAABgEgQ7AAAAk+AeOwAA7lB6erquX79u7zJQRBUvXlyOjo75MhbBDgDuwKRJk7Rs2TIdOHBArq6uatSokd5++21VrVrV2uba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/15dunRR//79lZ6ervDwcK1evdqmX0ZGhubOnSt3d3eFhISoefPmOnjwoFavXi0HBwdVrVpVb7/9ttavX6+wsDDFxMRoz549Onr0qPz9/SVJn3zyiWrUqKHt27erQYMGmj59uvr27au+fftKkl5//XWtW7fOLlcKC81Tsfk1/1Pm+n//BuPN+qSmpio5OdnmBQCAma1atUpubm5ycXFRmzZt1LVrV0VFRUmSatWqZRPqpH9OtrRv314VKlSQu7u7Nbz9+2xb7dq1rX/O/HmszEu2KSkpGjlypKpXry4vLy+5ublp//79Wca48cxcbiUkJKhfv37q2bOntm/frg0bNsjJyUmdO3e2eWghICBA7u7u1mVfX1+FhITIwcHBZl1mzfv375e/v7811ElSSEiIvLy8tH//fmubsLAwm3rs9XBUoTljZ8/5nyZNmqQJEyYU+H6BQivK094VAFlFJdm7AlNp3ry5Zs+eLScnJ5UvX97madjM3znOdPnyZUVGRioyMlKff/65vL29FR8fr8jIyCwPV9x42TNz0t2MjAxJ0siRI7V27Vq9++67qly5slxdXdW5c+csY/x7/35+flnu5/v777918eJF620Ns2bNkqenp9555x1rm88++0z+/v7aunWr9SrfjfVl1pjdusyai5pCccYuP+d/ylz/75sab9Zn9OjRSkpKsr6OHz9+B0cDAEDhV7JkSVWuXFkVKlS45RQnBw4c0IULF/TWW2/poYceUrVq1bJ9cOJWNm7cqF69eqlTp06qVauW/Pz8FBcXd8t+4eHhSkxMtN6DL0k//PCDMjIyrGfKrly5YnPWTZL1N1fvJKRVr15dx48ft8kG+/btU2JiokJCQqxtMu/Jy5TTswB3m12DnWEYGjx4sJYvX64ffvjhpvM/ZbrV/E+BgYHy8/Oz6ZOcnKytW7fm2MfZ2VkeHh42LwAA8I8KFSrIyclJ77//vv7880+tXLlSEydOzPM4wcHBWrZsmWJjY/Xrr7/q6aefzlXoql69ulq3bq1+/fpp27Zt2rhxowYPHqynnnpK5cuXlyS1a9dO27dv12uvvaZDhw5p165d6t27typWrKh69erludZMERERqlWrlrp3765du3Zp27Zt6tGjh5o2bWq9ZPz8889r7ty5mjdvnv744w/rXHr2YNdgl1/zP1WrVk3Lly+X9M/p02HDhun1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Qg0bNrSuDw4O1jvvvGNdfuWVV1SpUiVNmTJFklS1alXt2bNHb7/9dp7Hrl27tsaPH2/dz8yZMxUTE2NzfIUNwQ4AAEiSWrZsqYYNG2rJkiVydHTMsj08PNz652LFiql+/frav3+/TZv69evbLKekpCgqKkrffvutTp8+rb///ltXr161nrHLSXp6ut5880198cUXOnnypNLS0pSamqoSJUrYtAsNDbVZ3r9/v8LCwnKsOy9j165d22a5XLlyOnv27E3rtjeCHQAAkCS1a9dOX331lfbt26datW7vyd6SJUvaLI8cOVJr167Vu+++q8qVK8vV1VWdO3e+5YMOkydP1owZMzR9+nTVqlVLJUuW1LBhw7L0+/f+ciO3YxcvXtxm2WKxKCMjI8/7K0h2vcfup59+Uvv27VW+fHlZLBatWLHCZnvmTZT/fk2ePDnHMaOiorK0r1at2l0+EgAAig4nJyelp6dnWf/WW2+pZ8+eeuSRR7Rv374s27ds2WL9899//62dO3eqevXqN93Xxo0b1atXL3Xq1Em1atWSn59flocZsqtn48aN6tChg5555hnVqVNHQUFB+uOPP255bNWrV89yr9yNdd/J2EWBXYPd5cuXVadOHc2aNSvb7Zk3UWa+5s6dK4vFYr2+n5MaNWrY9Pvll1/uRvkAABRJAQEB2rp1q+Li4nT+/Hmbs1DvvvuuunfvrhYtWljvvcs0a9YsLV++XAcOHNCgQYP0119/qU+fPjfdV3BwsJYtW6bY2Fj9+uuvevrpp7Oc9QoICNBPP/2kkydP6vz589Z+a9eu1aZNm7R//371799fZ86cueWx/c///I8OHTqkF198UQcPHtTChQs1f/78LDXdzthFgV2DXZs2bfT666+rU6dO2W738/OzeX399ddq3ry5goKCbjpusWLFbPqVLVv2bpQPAECRNHLkSDk6OiokJETe3t5Z7nebNm2aunTpohYtWticyXrrrbf01ltvqU6dOvrll1+0cuXKW/4/durUqSpVqpQaNWqk9u3bKzIyUg888IBNm9dee01xcXGqVKmSvL29JUljxozRAw88oMjISDVr1kx+fn7q2LHjLY+tQoUK+uqrr7RixQrVqVNHc+bM0ZtvvmnT5nbHLgoshmEY9i5C+uey6/Lly3N8Y8+cOaP7779fCxYs0NNPP53jOFFRUZo8ebI8PT3l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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "helpers_summary = github_utils.summarize_user_metrics_for_repo(\n", + " combined,\n", + " repo=\"helpers\",\n", + ")\n", + "github_utils.plot_metrics_by_user(\n", + " helpers_summary,\n", + " repo=\"tutorials\",\n", + " metrics=['commits'],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "5b57c41c-163d-4aac-b55b-b223ae9de9a1", + "metadata": {}, + "source": [ + "\n", + "## See stats of a user on multiple repos based on `commits`, `prs`, `additions` and `deletions`" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "ce513fe8-1b34-4679-b3a9-fe00aa1b62a6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "krishna_summary = github_utils.summarize_repo_metrics_for_user(\n", + " combined,\n", + " user=\"tkpratardan\",\n", + ")\n", + "\n", + "# then plot PRs and commits across their repos\n", + "github_utils.plot_metrics_by_repo(\n", + " krishna_summary,\n", + " user=\"tkpratardan\",\n", + " metrics=['prs', 'commits','additions','deletions'],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "0bfdaf57-a6f3-4620-bfd8-c539cb1f0ffc", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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/vgDu3btwtGjR0s8xzlz5sDFxQX169dHVlYWwsLCYG9vX+LtiahoWVlZSExMRF5eHpKSknDo0CEEBQWhS5cuGDhwINTU1ODq6gpvb28sWrQIdevWxaNHj7B//35079690Es2AgMDMW7cOOjr66NTp07IysrC+fPn8ezZM0yaNAkmJibQ1tbGoUOHUKNGDWhpaSl9flWpUgWjRo3C1KlTYWRkBCsrKyxatAgvXryAn59fieb28uVLTJ06FT179oSNjQ0ePnyIqKgo+Pj4lMlrRxWDR+xIpW3atAnu7u5KH4rAq2B3/vx52NvbY/bs2Zg2bRpcXFxw//59jBo1SqHt5MmTMWDAAPj6+sLV1RV6enpvPVUxb948xMXFwdbWFsbGxoW28fb2xsqVK7FkyRLUr18f33//PYKDg8XlDUpCKpVi5syZaNiwIdq0aQN1dXVs3769xNsTUdEOHToEc3Nz1KxZE506dcLx48exatUq7N27F+rq6pBIJDhw4ADatGmDwYMHo27duujTpw/u378PU1PTQvscOnQofvzxRwQHB8PR0RFt27ZFSEiIeMROQ0MDq1atwvfffw8LCwt069at0H4WLlwIHx8fDBgwAI0bN8adO3dw+PBhGBoalmhu6urqePLkCQYOHIi6deuid+/e8PT0RGBg4Lu9WFQpSAThjcW4iIiIiOijxCN2RERERCqCwY6IiIhIRTDYEREREakIBjsiIiIiFcFgR0RERKQiGOyIiIiIVASDHREREZGKYLAjIiIiUhEMdkREREQqgsGOiIiISEUw2BERERGpCAY7IiIiIhXx/wDda/oNJ3A+FAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "krishna_summary_2 = github_utils.summarize_repo_metrics_for_user(\n", + " combined,\n", + " user=\"tkpratardan\",\n", + ")\n", + "\n", + "github_utils.plot_metrics_by_repo(\n", + " krishna_summary_2,\n", + " user=\"tkpratardan\",\n", + " metrics=['additions', 'deletions'],\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "94679d8c-745d-4679-b44d-e2f04951d8cb", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:github_utils:Generated 144 days in period.\n", + "INFO:github_utils:Built daily commit DataFrame rows=144.\n" + ] + } + ], + "source": [ + "krishna_daily_commits = github_utils.build_daily_commit_df(\n", + " client, org=\"causify-ai\",\n", + " repo=\"helpers\",\n", + " username=\"tkpratardan\",\n", + " period=(datetime.datetime(2025,1,1, tzinfo=datetime.timezone.utc),\n", + " datetime.datetime(2025,5,24, tzinfo=datetime.timezone.utc)),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "74b56187-49d3-4213-8d52-73dd0d2004ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
datecommitsrepouser
02025-01-010helperstkpratardan
12025-01-020helperstkpratardan
22025-01-030helperstkpratardan
32025-01-040helperstkpratardan
42025-01-050helperstkpratardan
52025-01-060helperstkpratardan
62025-01-070helperstkpratardan
72025-01-080helperstkpratardan
82025-01-090helperstkpratardan
92025-01-100helperstkpratardan
102025-01-111helperstkpratardan
112025-01-120helperstkpratardan
122025-01-130helperstkpratardan
132025-01-140helperstkpratardan
142025-01-150helperstkpratardan
152025-01-161helperstkpratardan
162025-01-170helperstkpratardan
172025-01-180helperstkpratardan
182025-01-190helperstkpratardan
192025-01-200helperstkpratardan
202025-01-211helperstkpratardan
212025-01-220helperstkpratardan
222025-01-231helperstkpratardan
232025-01-240helperstkpratardan
242025-01-250helperstkpratardan
\n", + "
" + ], + "text/plain": [ + " date commits repo user\n", + "0 2025-01-01 0 helpers tkpratardan\n", + "1 2025-01-02 0 helpers tkpratardan\n", + "2 2025-01-03 0 helpers tkpratardan\n", + "3 2025-01-04 0 helpers tkpratardan\n", + "4 2025-01-05 0 helpers tkpratardan\n", + "5 2025-01-06 0 helpers tkpratardan\n", + "6 2025-01-07 0 helpers tkpratardan\n", + "7 2025-01-08 0 helpers tkpratardan\n", + "8 2025-01-09 0 helpers tkpratardan\n", + "9 2025-01-10 0 helpers tkpratardan\n", + "10 2025-01-11 1 helpers tkpratardan\n", + "11 2025-01-12 0 helpers tkpratardan\n", + "12 2025-01-13 0 helpers tkpratardan\n", + "13 2025-01-14 0 helpers tkpratardan\n", + "14 2025-01-15 0 helpers tkpratardan\n", + "15 2025-01-16 1 helpers tkpratardan\n", + "16 2025-01-17 0 helpers tkpratardan\n", + "17 2025-01-18 0 helpers tkpratardan\n", + "18 2025-01-19 0 helpers tkpratardan\n", + "19 2025-01-20 0 helpers tkpratardan\n", + "20 2025-01-21 1 helpers tkpratardan\n", + "21 2025-01-22 0 helpers tkpratardan\n", + "22 2025-01-23 1 helpers tkpratardan\n", + "23 2025-01-24 0 helpers tkpratardan\n", + "24 2025-01-25 0 helpers tkpratardan" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "krishna_daily_commits[0:25]" + ] + }, + { + "cell_type": "markdown", + "id": "6d1814db-b00f-4d7f-b39d-4568a5abeb4c", + "metadata": {}, + "source": [ + "\n", + "## There are many more helper funcs to see and compare statistics. Look at github_utils for more info -> `tutorial_github_causify_style/github_utils.py`" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorial_github_causify_style/notebooks/github_utils_test.ipynb b/tutorial_github_causify_style/notebooks/github_utils_test.ipynb deleted file mode 100644 index bba214353a..0000000000 --- a/tutorial_github_causify_style/notebooks/github_utils_test.ipynb +++ /dev/null @@ -1,677 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "CONTENTS:\n", - "- [Github API to understand user Contribution](#github-api-to-understand-user-contribution)\n", - " - [Set your Github PAT](#set-your-github-pat)\n", - " - [Pre-feth all the data you need in cache](#pre-feth-all-the-data-you-need-in-cache)\n", - " - [Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period](#query-extraction-takes-time,-so-prefetch-all-data-in-cache-for-all-the-users,-repos-and-time-frames-you-need.-once-in-cache-there-are-several-utility-functions-to-help-understand-the-user-contribution.-following-is-the-data-we-will-fetch-for-users-in-multiple-repos-for-the-given-period)\n", - " - [Combine the data for statistics and visualizations](#combine-the-data-for-statistics-and-visualizations)\n", - " - [Compare users on a repo based on `commits`, `prs`, `additions` and `deletions`](#compare-users-on-a-repo-based-on-`commits`,-`prs`,-`additions`-and-`deletions`)\n", - " - [See stats of a user on multiple repos based on `commits`, `prs`, `additions` and `deletions`](#see-stats-of-a-user-on-multiple-repos-based-on-`commits`,-`prs`,-`additions`-and-`deletions`)\n", - " - [There are many more helper funcs to see and compare statistics. Look at github_utils for more info -> `tutorial_github_causify_style/github_utils.py`](#there-are-many-more-helper-funcs-to-see-and-compare-statistics.-look-at-github_utils-for-more-info-->-`tutorial_github_causify_style/github_utils.py`)" - ] - }, - { - "cell_type": "markdown", - "id": "8bdfbc31-a6d6-431e-b0ed-bdc69b8eec25", - "metadata": {}, - "source": [ - "\n", - "# Github API to understand user Contribution" - ] - }, - { - "cell_type": "markdown", - "id": "923ef379-8424-46df-9b60-29d35a63a331", - "metadata": {}, - "source": [ - "The numbers come straight from the upstream repo via the REST API, so they only include commits and PRs where you\u2019re the author or the committer on that repo. They **do not** pick up any work you did in a fork (or the individual commits squashed into a single merge), which is why they\u2019ll always undercount what GitHub Insights shows for your overall contributions.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "442cd592-3137-4d73-a113-655bf8dfd3fe", - "metadata": {}, - "outputs": [], - "source": [ - "!sudo /bin/bash -c \"(source /venv/bin/activate; pip install --quiet jupyterlab-vim PyGithub)\"\n", - "!jupyter labextension enable" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "268ddc35-9bb4-4e0a-b7f4-a8409baf9904", - "metadata": {}, - "outputs": [], - "source": [ - "import logging\n", - "import os\n", - "import datetime\n", - "import time\n", - "import importlib \n", - "\n", - "import github_utils\n", - "import helpers.hcache_simple as hcache\n", - "import helpers.hcache_simple as hcacsimp\n", - "from github import Github\n", - "\n", - "# Enable logging.\n", - "logging.basicConfig(level=logging.INFO)\n", - "_LOG = logging.getLogger(__name__)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "9c25ee1d-620b-485e-b98c-769c7fff8ab4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "importlib.reload(github_utils)" - ] - }, - { - "cell_type": "markdown", - "id": "6afd498b-8453-42e1-852c-ac093f8e0bfd", - "metadata": {}, - "source": [ - "\n", - "## Set your Github PAT" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "3220998c-1261-418f-859b-b20bb9a6cb61", - "metadata": {}, - "outputs": [], - "source": [ - "# Set your GitHub access token here.\n", - "os.environ[\"GITHUB_ACCESS_TOKEN\"] = \"YOUR_GITHUB_PAT\"" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "03983a64-78a2-49c3-9163-815cf0ef3a77", - "metadata": {}, - "outputs": [], - "source": [ - "access_token = os.getenv(\"GITHUB_ACCESS_TOKEN\")\n", - "if not access_token:\n", - " _LOG.error(\"GITHUB_ACCESS_TOKEN not set. Exiting.\")\n", - " raise ValueError(\"Set GITHUB_ACCESS_TOKEN environment variable\")\n", - "\n", - "client = github_utils.GitHubAPI(access_token=access_token).get_client()" - ] - }, - { - "cell_type": "markdown", - "id": "4cc7efd4-af91-44e8-9e3c-2bdbc8440c9d", - "metadata": {}, - "source": [ - "\n", - "## Pre-feth all the data you need in cache " - ] - }, - { - "cell_type": "markdown", - "id": "a7772ca8-b716-412a-8526-74977f0c3ae5", - "metadata": {}, - "source": [ - "\n", - "### Query extraction takes time, so prefetch all data in cache for all the users, repos and time frames you need. once in cache there are several utility functions to help understand the user contribution. Following is the data we will fetch for users in multiple repos for the given period \n", - "- Prs opened in the repo\n", - "- Commits done\n", - "- LOC [additions and deletions]" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "0002b5e0-6975-4058-b9cd-b06676c89d38", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:github_utils:Starting prefetch for repo helpers.\n", - "INFO:github_utils:Fetched 6 commits for causify-ai/helpers user=tkpratardan.\n", - "INFO:github_utils:Found 7 PRs for causify-ai/helpers user=tkpratardan.\n", - "INFO:github_utils:Fetched LOC stats for causify-ai/helpers user=tkpratardan entries=6.\n", - "INFO:github_utils:Fetched 0 commits for causify-ai/helpers user=Prahar08modi.\n", - "INFO:github_utils:Found 0 PRs for causify-ai/helpers user=Prahar08modi.\n", - "INFO:github_utils:Fetched LOC stats for causify-ai/helpers user=Prahar08modi entries=0.\n", - "INFO:github_utils:Starting prefetch for repo tutorials.\n", - "INFO:github_utils:Fetched 15 commits for causify-ai/tutorials user=tkpratardan.\n", - "INFO:github_utils:Found 19 PRs for causify-ai/tutorials user=tkpratardan.\n", - "INFO:github_utils:Fetched LOC stats for causify-ai/tutorials user=tkpratardan entries=15.\n", - "INFO:github_utils:Fetched 6 commits for causify-ai/tutorials user=Prahar08modi.\n", - "INFO:github_utils:Found 7 PRs for causify-ai/tutorials user=Prahar08modi.\n", - "INFO:github_utils:Fetched LOC stats for causify-ai/tutorials user=Prahar08modi entries=6.\n", - "INFO:github_utils:Starting prefetch for repo cmamp.\n", - "INFO:github_utils:Fetched 6 commits for causify-ai/cmamp user=tkpratardan.\n", - "INFO:github_utils:Found 5 PRs for causify-ai/cmamp user=tkpratardan.\n", - "INFO:github_utils:Fetched LOC stats for causify-ai/cmamp user=tkpratardan entries=6.\n", - "INFO:github_utils:Fetched 0 commits for causify-ai/cmamp user=Prahar08modi.\n", - "INFO:github_utils:Found 0 PRs for causify-ai/cmamp user=Prahar08modi.\n", - "INFO:github_utils:Fetched LOC stats for causify-ai/cmamp user=Prahar08modi entries=0.\n", - "INFO:github_utils:Prefetched 6 user-repo combos in 92.79 seconds for period 2025-01-01 00:00:00+00:00 to 2025-05-24 00:00:00+00:00.\n" - ] - } - ], - "source": [ - "github_utils.prefetch_periodic_user_repo_data(\n", - " client,\n", - " org=\"causify-ai\",\n", - " repos=[\"helpers\",\"tutorials\",\"cmamp\"],\n", - " users=[\"tkpratardan\",\"Prahar08modi\"],\n", - " period=(\n", - " datetime.datetime(2025, 1, 1, tzinfo=datetime.timezone.utc),\n", - " datetime.datetime(2025, 5, 24, tzinfo=datetime.timezone.utc),\n", - " ),\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "id": "4e6e1277-32f0-4fca-9c62-6f29eebb6a44", - "metadata": {}, - "source": [ - "\n", - "## Combine the data for statistics and visualizations" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d03e07fc-37f6-4d69-8c16-2bc4296d0334", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily PR DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily LOC DataFrame rows=144 (no data).\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily PR DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily PR DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily PR DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily LOC DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily PR DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily LOC DataFrame rows=144 (no data).\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily PR DataFrame rows=144.\n", - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily LOC DataFrame rows=144.\n" - ] - } - ], - "source": [ - "combined = github_utils.collect_all_metrics(\n", - " client, org=\"causify-ai\",\n", - " repos=[\"helpers\",\"tutorials\",\"cmamp\"],\n", - " users=[\"Prahar08modi\",\"tkpratardan\"],\n", - " period=(datetime.datetime(2025,1,1, tzinfo=datetime.timezone.utc),\n", - " datetime.datetime(2025,5,24, tzinfo=datetime.timezone.utc)),\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "eb0aa61c-60f4-4b85-841a-623e3d069913", - "metadata": {}, - "source": [ - "\n", - "## Compare users on a repo based on `commits`, `prs`, `additions` and `deletions`" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "62bfd155-8e08-4ddb-82a2-3ec9d9a2c9ca", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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ytnZWb/88ouefPJJPfTQQ+revbtq1KihH3/8kbnscM8R7EzEw8PD2ju2evVq7du3z9o7Jv0zDceYMWO0a9cuLV26VImJierSpUum47zxxhuaPHmytm3bpkKFCqlbt27WdRcvXlTz5s21evVq7dy5U82aNVNMTIyOHDlic4x33nlHVatW1c6dOzVixAht3LhRvr6+qlmzpnWbyMhIOTk5afPmzZKkGjVqyMnJSbNnz1ZaWpqSk5P16aefKjIyUi4uLtb9Dh48qO+++05xcXFasGCB/ve//6lFixb666+/tG7dOk2cOFHDhw+3Hjc9PV2tWrXS+fPntW7dOq1cuVJ//vmn2rdvbz3m559/rtjYWI0bN07btm1TyZIl9cEHH9zhOwLALBo2bCjDMDI95syZIw8PD8XHx+v06dO6du2aEhMT9dFHHykgIMDeZaMAcszBWMgVwzC0evVqxcfHq3///jpz5oyKFCmi//u//5Orq6t1u5sDWunSpfXee++pVq1aunjxos04t7Fjx6pBgwaSpKFDh6pFixa6evWq3N3dVbVqVVWtWtW67ZgxY7RkyRItW7ZM/fr1s7Y3btxYr7zyinV50aJF8vf3t6m7UKFCKlasmE6ePClJCgsL0/fff6927dqpV69eSktLU926dbVixQqb/dLT0zVr1ix5eXkpPDxcjRo10r59+7RixQo5OTmpfPnymjhxotasWaM6depo9erV+vXXX3Xo0CEFBwdLkj755BNFRERo69atqlWrlqZOnaru3bure/fukqS33npLq1atytRrBwCAI6PH7j62fPlyeXp6yt3dXdHR0Wrfvr1iY2Ml/XO7/c2hTvrnUmdMTIxCQkLk5eVlDW//7m2rUqWK9eeMgb8Zl2wvXryowYMHq2LFivL19ZWnp6f27NmT6Rg398zl1MmTJ9WjRw917txZW7du1bp16+Tq6qq2bdva3LQQGhoqLy8v63JAQIDCw8Pl5ORk05ZR8549exQcHGwNdZIUHh4uX19f7dmzx7pNnTp1bOqpW7durp8DAAD2RI/dfaxRo0aaOXOmXF1dFRQUZHM3bJEiRWy2vXTpkqKiohQVFaV58+bJz89PR44cUVRUVKabK26+7Jkx6W56erokafDgwVq5cqXeeecdlS1bVh4eHmrbtm2mY/z7/IGBgZnG8924cUPnz5+3fgXPjBkz5OPjo7ffftu6zWeffabg4GBt3rxZjzzySKb6MmrMqi2jZuCui/WxdwUA7CU22d4V2KDH7j5WpEgRlS1bViEhIbed4mTv3r06d+6cJkyYoMcee0wVKlTI8saJ29mwYYO6dOmiNm3aqHLlygoMDFRiYuJt96tbt66SkpK0fft2a9sPP/yg9PR0a0/Z5cuXbXrdJFlnbL+TkFaxYkUdPXpUR48etbb9/vvvSkpKUnh4uHWbjDF5GTZt2pTncwIAYA8EuwIiJCRErq6umj59uv78808tW7ZMY8aMyfVxypUrp6+++koJCQnatWuXnnvuuRyFrooVK6pZs2bq0aOHtmzZog0bNqhfv37q0KGDgoKCJEktWrTQ1q1b9eabb2r//v3asWOHunbtqlKlSlnvRMuLyMhIVa5cWR07dtSOHTu0ZcsWderUSQ0aNLBeMn7ppZc0a9YszZ49W3/88Yd1Lj0AAO4nBLsCws/PT3PmzNHixYsVHh6uCRMm6J133sn1caZMmaKiRYuqXr16iomJUVRUlB5++OEc7Ttv3jxVqFBBTzzxhJo3b65HH31UH330kXV948aNNX/+fC1dulTVq1dXs2bN5Obmpri4OHl4eOS61gwWi0Vff/21ihYtqscff1yRkZEqXbq0Fi1aZN2mffv2GjFihF599VXVqFFDhw8fVu/evfN8TgAA7MFimHwq/ZSUFPn4+Cg5OVne3t42665evapDhw4pLCxM7u7udqoQZsHnqQBjjB1QcN2DMXa3yjL/Ro8dAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsTGLt2rWyWCxKSkqydyl3hdmfHwAA+aGQvQtwSPf664Hy8HUkDRs2VLVq1TR16tT8rycPQkNDNXDgQA0cONDepQAAUGDRY4dsGYahGzdu3NNzXrt27Z6eDwAAMyHY3Ye6dOmidevWadq0abJYLLJYLEpMTLTZ5vLly4qOjlb9+vWVlJSkxMREWSwWLVy4UPXq1ZO7u7sqVaqkdevWWffJuNz53XffqUaNGnJzc9NPP/2kgwcPqlWrVgoICJCnp6dq1aqlVatWWfdr2LChDh8+rJdfftlajySdO3dOzz77rB544AEVLlxYlStX1oIFC2zqbNiwofr166eBAweqRIkSioqKkiStWLFCDz30kDw8PNSoUaNMzy+nxx4wYIBeffVVFStWTIGBgYqNjb3DVx8AAMdFsLsPTZs2TXXr1lWPHj104sQJnThxQsHBwdb1SUlJatKkidLT07Vy5Ur5+vpa1w0ZMkSvvPKKdu7cqbp16yomJkbnzp2zOf7QoUM1YcIE7dmzR1WqVNHFixfVvHlzrV69Wjt37lSzZs0UExOjI0eOSJK++uorPfjgg3rzzTet9UjS1atXVaNGDX377bfavXu3evbsqRdeeEFbtmyxOd/cuXPl6uqqDRs26MMPP9TRo0f11FNPKSYmRgkJCXrxxRc1dOhQm31yc+wiRYpo8+bNevvtt/Xmm29q5cqVd/weAADgiBhjdx/y8fGRq6urChcurMDAQEnS3r17JUknT55U+/btVa5cOc2fP1+urq42+/br109PP/20JGnmzJmKi4vT//73P7366qvWbd588001adLEulysWDFVrVrVujxmzBgtWbJEy5YtU79+/VSsWDE5OzvLy8vLWo8kPfDAAxo8eLB1uX///oqPj9fnn3+u2rVrW9vLlSunt99+27r8+uuvq0yZMpo8ebIkqXz58vr11181ceLEXB+7SpUqGjVqlPU877//vlavXm3z/AAAMAuCnck0adJEtWvX1qJFi+Ts7Jxpfd26da0/FypUSDVr1tSePXtstqlZs6bN8sWLFxUbG6tvv/1WJ06c0I0bN3TlyhVrj1120tLSNG7cOH3++ec6duyYrl27ptTUVBUuXNhmuxo1atgs79mzR3Xq1Mm27twcu0qVKjbLJUuW1OnTp29ZNwAA9yu7Xopdv369YmJiFBQUJIvFoqVLl2a77X/+8x9ZLBaHuQvUUbVo0ULr16/X77//nudjFClSxGZ58ODBWrJkicaNG6cff/xRCQkJqly58m1vdJg0aZKmTZum1157TWvWrFFCQoKioqIy7ffv8+VETo/t4uJis2yxWJSenp7r8wEAcD+wa7C7dOmSqlatqhkzZtxyuyVLlmjTpk0KCgq6R5U5PldXV6WlpWVqnzBhgjp37qwnnngiy3C3adMm6883btzQ9u3bVbFixVuea8OGDerSpYvatGmjypUrKzAwMNPNDFnVs2HDBrVq1UrPP/+8qlatqtKlS+uPP/647XOrWLFiprFyN9d9J8cGAMDM7BrsoqOj9dZbb6lNmzbZbnPs2DH1799f8+bNy9T7UpCFhoZq8+bNSkxM1NmzZ216od555x117NhRjRs3to69yzBjxgwtWbJEe/fuVd++ffX333+rW7dutzxXuXLl9NVXXykhIUG7du3Sc889l6nXKzQ0VOvXr9exY8d09uxZ634rV67Uzz//rD179qhXr146derUbZ/bf/7zH+3fv19DhgzRvn37NH/+fM2ZMydTTXk5NgAAZubQd8Wmp6frhRde0JAhQxQREZGjfVJTU5WSkmLzMKPBgwfL2dlZ4eHh8vPzyzTe7d1331W7du3UuHFjm56sCRMmaMKECapatap++uknLVu2TCVKlLjluaZMmaKiRYuqXr16iomJUVRUlB5++GGbbd58800lJiaqTJky8vPzkyQNHz5cDz/8sKKiotSwYUMFBgaqdevWt31uISEh+vLLL7V06VJVrVpVH374ocaNG2ezTV6PDQCAmVkMwzDsXYT0z9inJUuW2PxxHj9+vNasWaP4+HhZLJYcfbtBbGysRo8enak9OTlZ3t7eNm1Xr17VoUOHFBYWJnd39/x6Kg4pMTFRYWFh2rlzp6pVq2bvckypIH2e8C/3+ttqADiOPHx7VG6lpKTIx8cnyyzzbw7bY7d9+3ZNmzZNc+bMsU54mxPDhg1TcnKy9XH06NG7WCUAAIDjcNhg9+OPP+r06dMKCQlRoUKFVKhQIR0+fFivvPKKQkNDs93Pzc1N3t7eNg8AAICCwGHnsXvhhRcUGRlp0xYVFaUXXnhBXbt2tVNV96/Q0FA5yFV3AABwl9g12F28eFEHDhywLh86dEgJCQkqVqyYQkJCVLx4cZvtXVxcFBgYqPLly9/rUgEAAByeXYPdtm3b1KhRI+vyoEGDJEmdO3fONL0FAAAAbs2uwa5hw4a5ujz470lx8wvfRID8wOcIAGBvDjvG7l5wdXWVk5OTjh8/Lj8/P7m6uubqDlxAkgzD0LVr13TmzBk5OTnJ1dXV3iUBAAqoAh3snJycFBYWphMnTuj48eP2Lgf3ucKFCyskJEROTg57szkAwOQKdLCT/um1CwkJ0Y0bN7L87lUgJ5ydnVWoUCF6fAEAdlXgg530z7deuLi48F20AADgvsY1IwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmYddgt379esXExCgoKEgWi0VLly61rrt+/bpee+01Va5cWUWKFFFQUJA6deqk48eP269gAAAAB2bXYHfp0iVVrVpVM2bMyLTu8uXL2rFjh0aMGKEdO3boq6++0r59+/Tkk0/aoVIAAADHV8ieJ4+OjlZ0dHSW63x8fLRy5Uqbtvfff1+1a9fWkSNHFBISci9KBAAAuG/cV2PskpOTZbFY5Ovra+9SAAAAHI5de+xy4+rVq3rttdf07LPPytvbO9vtUlNTlZqaal1OSUm5F+UBAADY3X3RY3f9+nW1a9dOhmFo5syZt9x2/Pjx8vHxsT6Cg4PvUZUAAAD25fDBLiPUHT58WCtXrrxlb50kDRs2TMnJydbH0aNH71GlAAAA9uXQl2IzQt3+/fu1Zs0aFS9e/Lb7uLm5yc3N7R5UBwAA4FjsGuwuXryoAwcOWJcPHTqkhIQEFStWTCVLllTbtm21Y8cOLV++XGlpaTp58qQkqVixYnJ1dbVX2QAAAA7JrsFu27ZtatSokXV50KBBkqTOnTsrNjZWy5YtkyRVq1bNZr81a9aoYcOG96pMAACA+4Jdg13Dhg1lGEa262+1DgAAALYc/uYJAAAA5AzBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAk7BrsFu/fr1iYmIUFBQki8WipUuX2qw3DEMjR45UyZIl5eHhocjISO3fv98+xQIAADg4uwa7S5cuqWrVqpoxY0aW699++2299957+vDDD7V582YVKVJEUVFRunr16j2uFAAAwPEVsufJo6OjFR0dneU6wzA0depUDR8+XK1atZIkffLJJwoICNDSpUvVoUOHe1kqAACAw3PYMXaHDh3SyZMnFRkZaW3z8fFRnTp1tHHjRjtWBgAA4Jjs2mN3KydPnpQkBQQE2LQHBARY12UlNTVVqamp1uWUlJS7UyAAAICDcdgeu7waP368fHx8rI/g4GB7lwQAAHBPOGywCwwMlCSdOnXKpv3UqVPWdVkZNmyYkpOTrY+jR4/e1ToBAAAchcMGu7CwMAUGBmr16tXWtpSUFG3evFl169bNdj83Nzd5e3vbPAAAAAoCu46xu3jxog4cOGBdPnTokBISElSsWDGFhIRo4MCBeuutt1SuXDmFhYVpxIgRCgoKUuvWre1XNAAAgIOya7Dbtm2bGjVqZF0eNGiQJKlz586aM2eOXn31VV26dEk9e/ZUUlKSHn30UcXFxcnd3d1eJQMAADgsi2EYhr2LuJtSUlLk4+Oj5ORkLssCuDtifexdAQB7iU2+66fITZZx2DF2AAAAyB2CHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYRJ6CXenSpXXu3LlM7UlJSSpduvQdFwUAAIDcy1OwS0xMVFpaWqb21NRUHTt27I6LAgAAQO4Vys3Gy5Yts/4cHx8vHx8f63JaWppWr16t0NDQfCsOAAAAOZerYNe6dWtJksViUefOnW3Wubi4KDQ0VJMnT8634gAAAJBzuQp26enpkqSwsDBt3bpVJUqUuCtFAQAAIPdyFewyHDp0KL/rAAAAwB3KU7CTpNWrV2v16tU6ffq0tScvw6xZs+64MAAAAOROnoLd6NGj9eabb6pmzZoqWbKkLBZLftcFAACAXMpTsPvwww81Z84cvfDCC/ldDwAAAPIoT/PYXbt2TfXq1cvvWgAAAHAH8hTsXnzxRc2fPz+/awEAAMAdyNOl2KtXr+qjjz7SqlWrVKVKFbm4uNisnzJlSr4Ul5aWptjYWH322Wc6efKkgoKC1KVLFw0fPpxxfQAAAP+Sp2D3yy+/qFq1apKk3bt326zLz8A1ceJEzZw5U3PnzlVERIS2bdumrl27ysfHRwMGDMi38wAAAJhBnoLdmjVr8ruOLP38889q1aqVWrRoIUkKDQ3VggULtGXLlntyfgAAgPtJnsbY3Sv16tXT6tWr9ccff0iSdu3apZ9++knR0dHZ7pOamqqUlBSbBwAAQEGQpx67Ro0a3fKS6w8//JDngm42dOhQpaSkqEKFCnJ2dlZaWprGjh2rjh07ZrvP+PHjNXr06Hw5PwAAwP0kT8EuY3xdhuvXryshIUG7d+9W586d86MuSdLnn3+uefPmaf78+YqIiFBCQoIGDhyooKCgbM8zbNgwDRo0yLqckpKi4ODgfKsJAADAUeUp2L377rtZtsfGxurixYt3VNDNhgwZoqFDh6pDhw6SpMqVK+vw4cMaP358tsHOzc1Nbm5u+VYDAADA/SJfx9g9//zz+fo9sZcvX5aTk22Jzs7Omb6bFgAAAHnsscvOxo0b5e7unm/Hi4mJ0dixYxUSEqKIiAjt3LlTU6ZMUbdu3fLtHAAAAGaRp2D31FNP2SwbhqETJ05o27ZtGjFiRL4UJknTp0/XiBEj1KdPH50+fVpBQUHq1auXRo4cmW/nAAAAMAuLYRhGbnfq2rWrzbKTk5P8/PzUuHFjNW3aNN+Kyw8pKSny8fFRcnKyvL297V0OADOK9bF3BQDsJTb5rp8iN1kmTz12s2fPzlNhAAAAuHvuaIzd9u3btWfPHklSRESEqlevni9FAQAAIPfyFOxOnz6tDh06aO3atfL19ZUkJSUlqVGjRlq4cKH8/Pzys0YAAADkQJ6mO+nfv78uXLig3377TefPn9f58+e1e/dupaSkaMCAAfldIwAAAHIgTz12cXFxWrVqlSpWrGhtCw8P14wZMxzu5gkAAICCIk89dunp6XJxccnU7uLiwuTBAAAAdpKnYNe4cWO99NJLOn78uLXt2LFjevnll/XEE0/kW3EAAADIuTwFu/fff18pKSkKDQ1VmTJlVKZMGYWFhSklJUXTp0/P7xoBAACQA3kaYxccHKwdO3Zo1apV2rt3rySpYsWKioyMzNfiAAAAkHO56rH74YcfFB4erpSUFFksFjVp0kT9+/dX//79VatWLUVEROjHH3+8W7UCAADgFnIV7KZOnaoePXpk+XUWPj4+6tWrl6ZMmZJvxQEAACDnchXsdu3apWbNmmW7vmnTptq+ffsdFwUAAIDcy1WwO3XqVJbTnGQoVKiQzpw5c8dFAQAAIPdyFeweeOAB7d69O9v1v/zyi0qWLHnHRQEAACD3chXsmjdvrhEjRujq1auZ1l25ckWjRo1Sy5Yt8604AAAA5JzFMAwjpxufOnVKDz/8sJydndWvXz+VL19ekrR3717NmDFDaWlp2rFjhwICAu5awbmVkpIiHx8fJScnZ3nTBwDcsVgfe1cAwF5ik+/6KXKTZXI1j11AQIB+/vln9e7dW8OGDVNGJrRYLIqKitKMGTMcKtQBAAAUJLmeoLhUqVJasWKF/v77bx04cECGYahcuXIqWrTo3agPAAAAOZSnb56QpKJFi6pWrVr5WQsAAADuQJ6+KxYAAACOh2AHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDrgDx44d0/PPP6/ixYvLw8NDlStX1rZt2+xdFgCggCpk7wKA+9Xff/+t+vXrq1GjRvruu+/k5+en/fv3q2jRovYuDQBQQBHsgDyaOHGigoODNXv2bGtbWFiYHSsCABR0XIoF8mjZsmWqWbOmnnnmGfn7+6t69er6+OOP7V0WAKAAI9gBefTnn39q5syZKleunOLj49W7d28NGDBAc+fOtXdpAIACikuxQB6lp6erZs2aGjdunCSpevXq2r17tz788EN17tzZztUBAAoieuyAPCpZsqTCw8Nt2ipWrKgjR47YqSIAQEFHsAPyqH79+tq3b59N2x9//KFSpUrZqSIAQEFHsAPy6OWXX9amTZs0btw4HThwQPPnz9dHH32kvn372rs0AEAB5fDBjglg4ahq1aqlJUuWaMGCBapUqZLGjBmjqVOnqmPHjvYuDQBQQDn0zRNMAAtH17JlS7Vs2dLeZQAAIMnBgx0TwAIAAOScQ1+KzcsEsKmpqUpJSbF5AAAAFAQO3WOXMQHsoEGD9Prrr2vr1q0aMGCAXF1ds50nbPz48Ro9evQ9rlQKHfrtPT8nAMeQ6G7vCgDgHxbDMAx7F5EdV1dX1axZUz///LO1bcCAAdq6das2btyY5T6pqalKTU21LqekpCg4OFjJycny9va+a7US7ICCK9H9OXuXAMBeYpPv+ilSUlLk4+OToyzj0Jdi8zIBrJubm7y9vW0eAAAABYFDBzsmgAUAAMg5hw52TAALAACQcw4d7JgAFgAAIOcc+q5YiQlgAQAAcsqhe+wAAACQcwQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABM4r4KdhMmTJDFYtHAgQPtXQoAAIDDuW+C3datW/Xf//5XVapUsXcpAAAADum+CHYXL15Ux44d9fHHH6to0aL2LgcAAMAh3RfBrm/fvmrRooUiIyPtXQoAAIDDKmTvAm5n4cKF2rFjh7Zu3Zqj7VNTU5WammpdTklJuVulAQAAOBSH7rE7evSoXnrpJc2bN0/u7u452mf8+PHy8fGxPoKDg+9ylQAAAI7BYhiGYe8isrN06VK1adNGzs7O1ra0tDRZLBY5OTkpNTXVZp2UdY9dcHCwkpOT5e3tfddqDR367V07NgDHluj+nL1LAGAvscl3/RQpKSny8fHJUZZx6EuxTzzxhH799Vebtq5du6pChQp67bXXMoU6SXJzc5Obm9u9KhEAAMBhOHSw8/LyUqVKlWzaihQpouLFi2dqBwAAKOgceowdAAAAcs6he+yysnbtWnuXAAAA4JDosQMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACbh0MFu/PjxqlWrlry8vOTv76/WrVtr37599i4LAADAITl0sFu3bp369u2rTZs2aeXKlbp+/bqaNm2qS5cu2bs0AAAAh1PI3gXcSlxcnM3ynDlz5O/vr+3bt+vxxx+3U1UAAACOyaF77P4tOTlZklSsWDE7VwIAAOB4HLrH7mbp6ekaOHCg6tevr0qVKmW7XWpqqlJTU63LKSkp96I8AAAAu7tveuz69u2r3bt3a+HChbfcbvz48fLx8bE+goOD71GFAAAA9nVfBLt+/fpp+fLlWrNmjR588MFbbjts2DAlJydbH0ePHr1HVQIAANiXQ1+KNQxD/fv315IlS7R27VqFhYXddh83Nze5ubndg+oAAAAci0MHu759+2r+/Pn6+uuv5eXlpZMnT0qSfHx85OHhYefqAAAAHItDX4qdOXOmkpOT1bBhQ5UsWdL6WLRokb1LAwAAcDgO3WNnGIa9SwAAALhvOHSPHQAAAHKOYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEzivgh2M2bMUGhoqNzd3VWnTh1t2bLF3iUBAAA4HIcPdosWLdKgQYM0atQo7dixQ1WrVlVUVJROnz5t79IAAAAcisMHuylTpqhHjx7q2rWrwsPD9eGHH6pw4cKaNWuWvUsDAABwKIXsXcCtXLt2Tdu3b9ewYcOsbU5OToqMjNTGjRuz3Cc1NVWpqanW5eTkZElSSkrKXa01PfXyXT0+AMeVYjHsXQIAe7nL+eKfU/xzDsO4/e8ahw52Z8+eVVpamgICAmzaAwICtHfv3iz3GT9+vEaPHp2pPTg4+K7UCAA+9i4AgP1MuHe/AS5cuCAfn1ufz6GDXV4MGzZMgwYNsi6np6fr/PnzKl68uCwWix0rA2BGKSkpCg4O1tGjR+Xt7W3vcgCYkGEYunDhgoKCgm67rUMHuxIlSsjZ2VmnTp2yaT916pQCAwOz3MfNzU1ubm42bb6+vnerRACQJHl7exPsANw1t+upy+DQN0+4urqqRo0aWr16tbUtPT1dq1evVt26de1YGQAAgONx6B47SRo0aJA6d+6smjVrqnbt2po6daouXbqkrl272rs0AAAAh+Lwwa59+/Y6c+aMRo4cqZMnT6patWqKi4vLdEMFANiDm5ubRo0alWkICADYg8XIyb2zAAAAcHgOPcYOAAAAOUewAwAAMAmCHQAAgEkQ7ADAjmJjY1WtWjV7lwHAJAh2AEzn5MmT6t+/v0qXLi03NzcFBwcrJibGZk5MRzF48GCburp06aLWrVvbryAA9zWHn+4EAHIjMTFR9evXl6+vryZNmqTKlSvr+vXrio+PV9++fbP9nml78fT0lKenp73LAGAS9NgBMJU+ffrIYrFoy5Ytevrpp/XQQw8pIiJCgwYN0qZNmyRJR44cUatWreTp6Slvb2+1a9fO5qsLMy6Pzpo1SyEhIfL09FSfPn2Ulpamt99+W4GBgfL399fYsWNtzm2xWPTf//5XLVu2VOHChVWxYkVt3LhRBw4cUMOGDVWkSBHVq1dPBw8ezHSujJ/nzp2rr7/+WhaLRRaLRWvXrtW1a9fUr18/lSxZUu7u7ipVqpTGjx9/919MAPcdgh0A0zh//rzi4uLUt29fFSlSJNN6X19fpaenq1WrVjp//rzWrVunlStX6s8//1T79u1ttj148KC+++47xcXFacGCBfrf//6nFi1a6K+//tK6des0ceJEDR8+XJs3b7bZb8yYMerUqZMSEhJUoUIFPffcc+rVq5eGDRumbdu2yTAM9evXL8v6Bw8erHbt2qlZs2Y6ceKETpw4oXr16um9997TsmXL9Pnnn2vfvn2aN2+eQkND8+11A2AeXIoFYBoHDhyQYRiqUKFCttusXr1av/76qw4dOqTg4GBJ0ieffKKIiAht3bpVtWrVkvTP91LPmjVLXl5eCg8PV6NGjbRv3z6tWLFCTk5OKl++vCZOnKg1a9aoTp061uN37dpV7dq1kyS99tprqlu3rkaMGKGoqChJ0ksvvZTtVyJ6enrKw8NDqampCgwMtLYfOXJE5cqV06OPPiqLxaJSpUrd2QsFwLTosQNgGjn5Ip09e/YoODjYGuokKTw8XL6+vtqzZ4+1LTQ0VF5eXtblgIAAhYeHy8nJyabt9OnTNsevUqWKzXpJqly5sk3b1atXlZKSkuPn1aVLFyUkJKh8+fIaMGCAvv/++xzvC6BgIdgBMI1y5crJYrHkyw0SLi4uNssWiyXLtvT09Gz3s1gs2bb9e79befjhh3Xo0CGNGTNGV65cUbt27dS2bdsc7w+g4CDYATCNYsWKKSoqSjNmzNClS5cyrU9KSlLFihV19OhRHT161Nr++++/KykpSeHh4fey3Cy5uroqLS0tU7u3t7fat2+vjz/+WIsWLdKXX36p8+fP26FCAI6MYAfAVGbMmKG0tDTVrl1bX375pfbv3689e/bovffeU926dRUZGanKlSurY8eO2rFjh7Zs2aJOnTqpQYMGqlmzpr3LV2hoqH755Rft27dPZ8+e1fXr1zVlyhQtWLBAe/fu1R9//KHFixcrMDBQvr6+9i4XgIMh2AEwldKlS2vHjh1q1KiRXnnlFVWqVElNmjTR6tWrNXPmTFksFn399dcqWrSoHn/8cUVGRqp06dJatGiRvUuXJPXo0UPly5dXzZo15efnpw0bNsjLy0tvv/22atasqVq1aikxMdF6EwcA3Mxi5GS0MQAAABwe/90DAAAwCYIdAACASRDsAAAATIJgBwAAYBIEOwAAAJMg2AEAAJgEwQ4AAMAkCHYAAAAmQbADAAAwCYIdAACASRDsAAAATIJgBwAAYBL/H2dWWG4bRT5HAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "helpers_summary = github_utils.summarize_user_metrics_for_repo(\n", - " combined,\n", - " repo=\"tutorials\",\n", - ")\n", - "github_utils.plot_metrics_by_user(\n", - " helpers_summary,\n", - " repo=\"tutorials\",\n", - " metrics=['commits'],\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "id": "5b57c41c-163d-4aac-b55b-b223ae9de9a1", - "metadata": {}, - "source": [ - "\n", - "## See stats of a user on multiple repos based on `commits`, `prs`, `additions` and `deletions`" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "ce513fe8-1b34-4679-b3a9-fe00aa1b62a6", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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fYzjx49XZGRkrutcG0iL02uvvaYhQ4Zo2bJl+uabbzR27FjFxsZq69attgd/UDIIdihR/fr100MPPaStW7fq008/zXO5OnXqaO3atWrXrt11/+EojqE2si/17dq1q1Afbr6+vvLy8tKuXbvyXS4oKEj79u3L0Z59Wau4x4Hbv39/jrbff/9dFStWtIXizz//XNHR0Xrttddsy1y+fDnXJxcL69Zbb9Wtt96qF198UQsXLtR9992nTz75RMOHD1dQUJDWrl2r8+fP2/XaldS5uFZJvRcF+cf8448/Vp8+fTRgwACtXLnS9gT332X3rPx9e7///rukvx5Cup6Cvq951bt+/XqdOXNGS5YsUYcOHWztCQkJ1913tqCgIMXFxSktLc0uzF973s+dO6e4uDhNmTLF7gGg3H5+b8Svv/6q33//XQsWLLB7kObay5whISGSdN3f57wEBQUpKytL+/fvt/UAS389sJOcnJzjZyu/3xPpr56v3r17q3fv3srKytIjjzyid999VxMnTix0CMs+NhcXF0VERBRonf3796tz58626bS0NB07dkw9evSwHa/01/uavX3prxEPEhIScuwnPDxc4eHhev7557V582a1a9dO77zzjl544YVCHQsKh0uxKFEeHh6aM2eOYmJi1Lt37zyXGzhwoDIzMzVt2rQc865evWr3j1SlSpVuOIx069ZNnp6eio2N1eXLl+3m5dcT4OTkpL59++p///ufduzYkWN+9ro9evTQtm3btGXLFtu8Cxcu6L333lPt2rXVsGHDG6r/Wlu2bLG7P+nw4cNatmyZunXrZuvxcHZ2znFsM2fOzDGkRWGcO3cuxzabNWsmSbbLTD169FBmZqZmzZplt9wbb7whi8Vie2q6pJTUe5H9FHF+P4uurq5asmSJWrVqpd69e2vbtm05ljl69Kjt6UlJSk1N1QcffKBmzZoVaLzHgr6vlSpVyrXe7J+Pv28jIyNDb7/99nX3na1Hjx66evWq5syZY2vLzMzUzJkzr7svScX+1W+57ccwjBxDh/j6+qpDhw6aO3eukpKS7OYVpIc4O/BcW//rr78uSerZs6ekgv2eXDvci5OTk+0p62uHTimI6tWrq1OnTnr33Xd17NixHPOzb9H4u/fee8/uHsA5c+bo6tWrtt/RiIgIubq66q233rI7nv/+979KSUmxHW9qamqO+4DDw8Pl5ORUpGNB4dBjhxKX25AH1+rYsaMeeughxcbGKj4+Xt26dZOLi4v279+vxYsX680337Tdn9eiRQvNmTNHL7zwgurWravq1avr9ttvL1RNXl5eeuONNzR8+HC1atXKNjbVzz//rIsXL+Z76eOll17SN998o44dO2rkyJFq0KCBjh07psWLF2vTpk3y8fHRs88+axvqZezYsapSpYoWLFighIQEffHFF3Y3HheHxo0bKzIy0m64E+mvMday9erVSx9++KG8vb3VsGFDbdmyRWvXrs1zCJGCWLBggd5++23169dPderU0fnz5/X+++/Ly8vL9o9e79691blzZ/3rX/9SYmKimjZtqm+++UbLli3T448/bvegREkoqffC3d1dDRs21Keffqp69eqpSpUqaty4cY77tdzd3bV8+XLdfvvtioqK0oYNG+yWqVevnh588EFt375dfn5+mjt3rk6cOKF58+YVqI6Cvq/NmjWTs7OzXn75ZaWkpMhqter2229X27ZtVblyZUVHR2vs2LGyWCz68MMPC3Xpu3fv3mrXrp2effZZJSYm2sbiu/aeKi8vL3Xo0EHTp0/XlStXVKtWLX3zzTeF6h0siPr166tOnToaP368/vzzT3l5eemLL77I9b68t956S+3bt9fNN9+skSNHKjg4WImJifr6668VHx+f736aNm2q6Ohovffee7ZL2tu2bdOCBQvUt29fW+9XQX5Phg8frrNnz+r222/XTTfdpEOHDmnmzJlq1qyZXW9gYcyePVvt27dXeHi4RowYoZCQEJ04cUJbtmzRkSNH9PPPP9stn5GRoS5dumjgwIHat2+f3n77bbVv31533HGHpL+C8IQJEzRlyhR1795dd9xxh225Vq1a2e7L/PbbbzVmzBgNGDBA9erV09WrV/Xhhx/K2dlZd911V5GOBYVQqs/gwvT+PtxJfq4d7iTbe++9Z7Ro0cJwd3c3PD09jfDwcOPpp582jh49alvm+PHjRs+ePQ1PT09Dkm3ok/z2fe0wHdm++uoro23btoa7u7vh5eVl3HLLLcaiRYuue5yHDh0yBg8ebPj6+hpWq9UICQkxRo8ebaSnp9uWOXjwoNG/f3/Dx8fHcHNzM2655RZj+fLldtvJHmLj2mEB8jqW7GEXTp06ZWvT/x/i46OPPjJCQ0MNq9VqNG/ePMewFufOnTOG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770nHx8fbdiwQb169bK1Dx06VAMHDpQkPfPMM2rTpo0mTpxot6+hQ4fabevy5cv64IMPVKtWLUnSzJkz1bNnT7322mvy9/cvprNSMPTYAQCAMmXPnj1KT09Xly5d8lymSZMmtr9n9+SFh4fbtWV/TZf01/dWjxgxQqGhofL29paXl5fS0tKUlJRU6O1evnxZqamptrbAwEBbqJOkNm3aKCsrS/v27SvwMRcXeuwAkwhfEH79haBfo391dAkAriP7K7by4+LiYvt79uC+17ZlZWXZpqOjo3XmzBm9+eabCgoKktVqVZs2bZSRkVHo7Uqy23ZZQo8dAAAoU0JDQ+Xu7q64uLhi2+b333+vsWPHqkePHmrUqJGsVqtOnz5dLNtOSkrS0aNHbdNbt26Vk5OTwsLCimX7hUGPHQAAKFPc3Nz0zDPP6Omnn5arq6vatWunU6dO6bfffsv38mx+QkND9eGHH6ply5ZKTU3VU089VaCewYLWGx0drVdffVWpqakaO3asBg4cWOr310kEOwAAUAZNnDhRFSpU0KRJk3T06FHVqFFDDz/8cJG399///lcjR47UzTffrICAAL300ksaP358sdRat25d3XnnnerRo4fOnj2rXr166e233y6WbReWxTAMwyF7LsNSU1Pl7e2tlJQUeXl5ObocoEC4x65guMcO/ySXL19WQkKCgoOD5ebm5uhyTCkmJkZLly5VfHz8DW0nv/eqMLmEe+wAAABMgmAHAABgEgQ7AACAIoqJibnhy7DFiWAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAChTOnXqpMcff7zI68fExKhZs2bFVk95wnfFAgDwTxPjXcr7Synd/f2D0WMHAABQSIZh6OrVq44uIweCHQAAKHOysrL09NNPq0qVKvL391dMTIxtXnJysoYPHy5fX195eXnp9ttv188//5zntoYMGaK+fftqypQptnUefvhhZWRk2O0vNjZWwcHBcnd3V9OmTfX555/b5q9fv14Wi0UrV65UixYtZLVatWnTJv3888/q3LmzPD095eXlpRYtWmjHjh0lck4KgkuxAACgzFmwYIHGjRunH374QVu2bNGQIUPUrl07de3aVQMGDJC7u7tWrlwpb29vvfvuu+rSpYt+//13ValSJdftxcXFyc3NTevXr1diYqKGDh2qqlWr6sUXX5QkxcbG6qOPPtI777yj0NBQbdy4Uffff798fX3VsWNH23aeffZZvfrqqwoJCVHlypXVoUMHNW/eXHPmzJGzs7Pi4+Pl4uJSKucoNwQ7AABQ5jRp0kSTJ0+WJIWGhmrWrFmKi4uTu7u7tm3bppMnT8pqtUqSXn31VS1dulSff/65Ro4cmev2XF1dNXfuXFWsWFGNGjXS1KlT9dRTT2natGm6cuWKXnrpJa1du1Zt2rSRJIWEhGjTpk1699137YLd1KlT1bVrV9t0UlKSnnrqKdWvX99WqyMR7AAAQJnTpEkTu+kaNWro5MmT+vnnn5WWlqaqVavazb906ZIOHjyY5/aaNm2qihUr2qbbtGmjtLQ0HT58WGlpabp48aJdYJOkjIwMNW/e3K6tZcuWdtPjxo3T8OHD9eGHHyoiIkIDBgxQnTp1CnWsxYlgBwAAypxrL2daLBZlZWUpLS1NNWrU0Pr163Os4+PjU6R9paWlSZK+/vpr1apVy25edq9gtkqVKtlNx8TE6N5779XXX3+tlStXavLkyfrkk0/Ur1+/ItVyowh2AACg3Lj55pt1/PhxVahQQbVr1y7wej///LMuXbokd3d3SdLWrVvl4eGhgIAAValSRVarVUlJSXaXXQuqXr16qlevnp544gkNGjRI8+bNI9gBAABcT0REhNq0aaO+fftq+vTpqlevno4ePaqvv/5a/fr1y3GpNFtGRoYefPBBPf/880pMTNTkyZM1ZswYOTk5ydPTU+PHj9cTTzyhrKwstW/fXikpKfr+++/l5eWl6OjoXLd56dIlPfXUU+rfv7+Cg4N15MgRbd++XXfddVdJnoJ8EewAAEC5YbFYtGLFCv3rX//S0KFDderUKfn7+6tDhw7y8/PLc70uXbooNDRUHTp0UHp6ugYNGmQ3hMq0adPk6+ur2NhY/fHHH/Lx8dHNN9+s5557Ls9tOjs768yZMxo8eLBOnDihatWq6c4779SUKVOK85ALxWIYhuGonW/cuFGvvPKKfvzxRx07dkxffvml+vbt+3/FWSy5rjd9+nQ99dRTuc6LiYnJcULDwsK0d+/eAteVmpoqb29vpaSkyMvLq8DrAY4UviDc0SWUC79G/+roEoBSc/nyZSUkJCg4OFhubm6OLsdhhgwZouTkZC1dutTRpeQpv/eqMLnEoQMUX7hwQU2bNtXs2bNznX/s2DG719y5c2WxWK7bxdmoUSO79TZt2lQS5QMAAJQpDr0UGxUVpaioqDzn+/v7200vW7ZMnTt3VkhISL7brVChQo51AQAAzK7c3GN34sQJff3111qwYMF1l92/f79q1qwpNzc3tWnTRrGxsQoMDCyFKgEAQFkzf/58R5dQaspNsFuwYIE8PT1155135rtc69atNX/+fIWFhenYsWOaMmWKbrvtNu3atUuenp65rpOenq709HTbdGpqarHWDgAAUBrKTbCbO3eu7rvvvuve/Pn3S7tNmjRR69atFRQUpM8++0wPPvhgruvExsY69AkWAACA4uDQhycK6rvvvtO+ffs0fPjwQq/r4+OjevXq6cCBA3kuM2HCBKWkpNhehw8fvpFyAQAAHKJcBLv//ve/atGihZo2bVroddPS0nTw4EHVqFEjz2WsVqu8vLzsXgAAAOWNQ4NdWlqa4uPjFR8fL0lKSEhQfHy8kpKSbMukpqZq8eLFefbWdenSRbNmzbJNjx8/Xhs2bFBiYqI2b96sfv36ydnZWYMGDSrRYwEAAHA0h95jt2PHDnXu3Nk2PW7cOElSdHS07QmWTz75RIZh5BnMDh48qNOnT9umjxw5okGDBunMmTPy9fVV+/bttXXrVvn6+pbcgQAAAJQBDg12nTp10vW++GLkyJEaOXJknvMTExPtpj/55JPiKA0AAPyDderUSc2aNdOMGTMKtPz69evVuXNnnTt3Tj4+PiVaW37KzVOxAACgeJT2VxAW9qv8ChuqpL++UnTp0qW227tu1JIlS+Ti4lIs2ypNBDsAAID/LyMjQ66urqpSpYqjSymScvFULAAA+GcYMmSINmzYoDfffFMWi0UWi0Xz58/PcXlz6dKlslgskv76ZokpU6bo559/tltHkpKSktSnTx95eHjIy8tLAwcO1IkTJ2zbiYmJUbNmzfSf//xHwcHBtvFyO3XqpMcff9y23IcffqiWLVvK09NT/v7+uvfee3Xy5Mk8j+PQoUPq3bu3KleurEqVKqlRo0ZasWJF8ZykfNBjBwAAyow333xTv//+uxo3bqypU6dKkr7++ut817n77ru1a9curVq1SmvXrpUkeXt7KysryxbqNmzYoKtXr2r06NG6++67tX79etv6Bw4c0BdffKElS5bI2dk5131cuXJF06ZNU1hYmE6ePKlx48Zp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PXu2Lly4kGN+cnKyGjRokOMetd27dys5OVkNGzYszXJz5erqqszMzBztXl5euvvuu/X+++/r008/1RdffKGzZ886oEKUFO6xA27Q8uXL9ccff6hDhw6qXLmyVqxYoaysLNsTswDKn9mzZ6tdu3a65ZZbNHXqVDVp0kRXr17VmjVrNGfOHO3evVvh4eG67777NGPGDF29elWPPPKIOnbsqJYtWzq6fNWuXVurV6/Wvn37VLVqVXl7e2vmzJmqUaOGmjdvLicnJy1evFj+/v7y8fFxdLkoRvTYATfIx8dHS5Ys0e23364GDRronXfe0aJFi9SoUSNHlwagiEJCQrRz50517txZTz75pBo3bqyuXbsqLi5Oc+bMkcVi0bJly1S5cmV16NBBERERCgkJ0aeffuro0iVJI0aMUFhYmFq2bClfX199//338vT01PTp09WyZUu1atVKiYmJtoc4YB4WoyB3iQIAAKDMI6YDAACYBMEOAADAJAh2AAAAJkGwAwAAMAmCHQAAgEkQ7AAAAEyCYAcAAGASBDsAAACTINgBAACYBMEOAADAJAh2AAAAJkGwAwAAMIn/B49RngmZVFdjAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "krishna_summary = github_utils.summarize_repo_metrics_for_user(\n", - " combined,\n", - " user=\"tkpratardan\",\n", - ")\n", - "\n", - "# then plot PRs and commits across their repos\n", - "github_utils.plot_metrics_by_repo(\n", - " krishna_summary,\n", - " user=\"tkpratardan\",\n", - " metrics=['prs', 'commits'],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "0bfdaf57-a6f3-4620-bfd8-c539cb1f0ffc", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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/vgDu3btwtGjR0s8xzlz5sDFxQX169dHVlYWwsLCYG9vX+LtiahoWVlZSExMRF5eHpKSknDo0CEEBQWhS5cuGDhwINTU1ODq6gpvb28sWrQIdevWxaNHj7B//35079690Es2AgMDMW7cOOjr66NTp07IysrC+fPn8ezZM0yaNAkmJibQ1tbGoUOHUKNGDWhpaSl9flWpUgWjRo3C1KlTYWRkBCsrKyxatAgvXryAn59fieb28uVLTJ06FT179oSNjQ0ePnyIqKgo+Pj4lMlrRxWDR+xIpW3atAnu7u5KH4rAq2B3/vx52NvbY/bs2Zg2bRpcXFxw//59jBo1SqHt5MmTMWDAAPj6+sLV1RV6enpvPVUxb948xMXFwdbWFsbGxoW28fb2xsqVK7FkyRLUr18f33//PYKDg8XlDUpCKpVi5syZaNiwIdq0aQN1dXVs3769xNsTUdEOHToEc3Nz1KxZE506dcLx48exatUq7N27F+rq6pBIJDhw4ADatGmDwYMHo27duujTpw/u378PU1PTQvscOnQofvzxRwQHB8PR0RFt27ZFSEiIeMROQ0MDq1atwvfffw8LCwt069at0H4WLlwIHx8fDBgwAI0bN8adO3dw+PBhGBoalmhu6urqePLkCQYOHIi6deuid+/e8PT0RGBg4Lu9WFQpSAThjcW4iIiIiOijxCN2RERERCqCwY6IiIhIRTDYEREREakIBjsiIiIiFcFgR0RERKQiGOyIiIiIVASDHREREZGKYLAjIiIiUhEMdkREREQqgsGOiIiISEUw2BERERGpCAY7IiIiIhXx/wDda/oNJ3A+FAAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "krishna_summary_2 = github_utils.summarize_repo_metrics_for_user(\n", - " combined,\n", - " user=\"tkpratardan\",\n", - ")\n", - "\n", - "github_utils.plot_metrics_by_repo(\n", - " krishna_summary_2,\n", - " user=\"tkpratardan\",\n", - " metrics=['additions', 'deletions'],\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "94679d8c-745d-4679-b44d-e2f04951d8cb", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:github_utils:Generated 144 days in period.\n", - "INFO:github_utils:Built daily commit DataFrame rows=144.\n" - ] - } - ], - "source": [ - "krishna_daily_commits = github_utils.build_daily_commit_df(\n", - " client, org=\"causify-ai\",\n", - " repo=\"helpers\",\n", - " username=\"tkpratardan\",\n", - " period=(datetime.datetime(2025,1,1, tzinfo=datetime.timezone.utc),\n", - " datetime.datetime(2025,5,24, tzinfo=datetime.timezone.utc)),\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "74b56187-49d3-4213-8d52-73dd0d2004ab", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
datecommitsrepouser
02025-01-010helperstkpratardan
12025-01-020helperstkpratardan
22025-01-030helperstkpratardan
32025-01-040helperstkpratardan
42025-01-050helperstkpratardan
52025-01-060helperstkpratardan
62025-01-070helperstkpratardan
72025-01-080helperstkpratardan
82025-01-090helperstkpratardan
92025-01-100helperstkpratardan
102025-01-111helperstkpratardan
112025-01-120helperstkpratardan
122025-01-130helperstkpratardan
132025-01-140helperstkpratardan
142025-01-150helperstkpratardan
152025-01-161helperstkpratardan
162025-01-170helperstkpratardan
172025-01-180helperstkpratardan
182025-01-190helperstkpratardan
192025-01-200helperstkpratardan
202025-01-211helperstkpratardan
212025-01-220helperstkpratardan
222025-01-231helperstkpratardan
232025-01-240helperstkpratardan
242025-01-250helperstkpratardan
\n", - "
" - ], - "text/plain": [ - " date commits repo user\n", - "0 2025-01-01 0 helpers tkpratardan\n", - "1 2025-01-02 0 helpers tkpratardan\n", - "2 2025-01-03 0 helpers tkpratardan\n", - "3 2025-01-04 0 helpers tkpratardan\n", - "4 2025-01-05 0 helpers tkpratardan\n", - "5 2025-01-06 0 helpers tkpratardan\n", - "6 2025-01-07 0 helpers tkpratardan\n", - "7 2025-01-08 0 helpers tkpratardan\n", - "8 2025-01-09 0 helpers tkpratardan\n", - "9 2025-01-10 0 helpers tkpratardan\n", - "10 2025-01-11 1 helpers tkpratardan\n", - "11 2025-01-12 0 helpers tkpratardan\n", - "12 2025-01-13 0 helpers tkpratardan\n", - "13 2025-01-14 0 helpers tkpratardan\n", - "14 2025-01-15 0 helpers tkpratardan\n", - "15 2025-01-16 1 helpers tkpratardan\n", - "16 2025-01-17 0 helpers tkpratardan\n", - "17 2025-01-18 0 helpers tkpratardan\n", - "18 2025-01-19 0 helpers tkpratardan\n", - "19 2025-01-20 0 helpers tkpratardan\n", - "20 2025-01-21 1 helpers tkpratardan\n", - "21 2025-01-22 0 helpers tkpratardan\n", - "22 2025-01-23 1 helpers tkpratardan\n", - "23 2025-01-24 0 helpers tkpratardan\n", - "24 2025-01-25 0 helpers tkpratardan" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "krishna_daily_commits[0:25]" - ] - }, - { - "cell_type": "markdown", - "id": "6d1814db-b00f-4d7f-b39d-4568a5abeb4c", - "metadata": {}, - "source": [ - "\n", - "## There are many more helper funcs to see and compare statistics. Look at github_utils for more info -> `tutorial_github_causify_style/github_utils.py`" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From ca43109cba02f6bb8c699a3bd08e57c899fee631 Mon Sep 17 00:00:00 2001 From: GP Saggese Date: Mon, 2 Jun 2025 08:05:51 -0400 Subject: [PATCH 8/8] Move amp fwd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-commit checks: All checks passed ✅ --- helpers_root | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers_root b/helpers_root index 0387ed7fa9..a77012a630 160000 --- a/helpers_root +++ b/helpers_root @@ -1 +1 @@ -Subproject commit 0387ed7fa93653b9ca98396fb3580a7fa7a19ba3 +Subproject commit a77012a630039408e7e860e481ff86deda1ad5b5