From 675704225af4ca90db156f1417cd90e0e6342247 Mon Sep 17 00:00:00 2001 From: Enzo Nunes Date: Sun, 23 Feb 2025 22:27:35 +0000 Subject: [PATCH] add PICable script --- PICable.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 PICable.py diff --git a/PICable.py b/PICable.py new file mode 100644 index 0000000..554c9f0 --- /dev/null +++ b/PICable.py @@ -0,0 +1,86 @@ +import os +import subprocess +import sys +from datetime import datetime, timedelta + +import requests + +LIMIT_COMMITS_30_DAYS = 50 # Has to be <= 100 +LIMIT_STARS = 200 +LIMIT_NLOC = 100000 +MARGIN = 0.1 + + +def get_stars_info(owner, repo, token): + headers = {"Authorization": f"token {token}"} + stars_url = f"https://api.github.com/repos/{owner}/{repo}" + stars_response = requests.get(stars_url, headers=headers).json() + stars = stars_response["stargazers_count"] + return stars + + +def get_commits_last_30_days(owner, repo, token): + headers = {"Authorization": f"token {token}"} + since = (datetime.now() - timedelta(days=30)).isoformat() + print(since) + commits_url = f"https://api.github.com/repos/{owner}/{repo}/commits?since={since}&per_page={LIMIT_COMMITS_30_DAYS}" + commits_response = requests.get(commits_url, headers=headers).json() + commits_30_days = len(commits_response) + return commits_30_days + + +def get_lines_of_code(owner, repo): + repo_url = f"https://github.com/{owner}/{repo}.git" + clone_dir = os.path.expanduser("~/temp/PICable") + + subprocess.run(["git", "clone", repo_url, clone_dir], check=True, stdout=sys.stdout, stderr=sys.stderr) + result = subprocess.run(["sloccount", clone_dir], capture_output=True, text=True, check=True) + for line in result.stdout.splitlines(): + if "Total Physical Source Lines of Code (SLOC)" in line: + loc = int(line.split()[8].replace(",", "")) + break + else: + loc = 0 + subprocess.run(["rm", "-rf", clone_dir], check=True) + + return loc + + +def PICable(owner, repository, token): + margin_percentage = round(MARGIN * 100) + res = "" + + stars = get_stars_info(owner, repository, token) + if stars >= LIMIT_STARS: + res += f"The repository has over {LIMIT_STARS} stars. ✅\n" + elif stars >= LIMIT_STARS * (1 - MARGIN): + res += f"The repository has {stars}, which is close to the limit of {LIMIT_STARS} stars, considering a {margin_percentage}% margin. ⭕\n" + else: + res += f"The repository has {stars} stars, which is way below the limit of {LIMIT_STARS} stars, considering a {margin_percentage}% margin. ❌\n" + + commits_30_days = get_commits_last_30_days(owner, repository, token) + if commits_30_days >= LIMIT_COMMITS_30_DAYS: + res += f"The repository has over {LIMIT_COMMITS_30_DAYS} commits in the last 30 days. ✅\n" + elif commits_30_days >= LIMIT_COMMITS_30_DAYS * (1 - MARGIN): + res += f"The repository has {commits_30_days} commits in the last 30 days, which is close to the limit of {LIMIT_COMMITS_30_DAYS} commits, considering a {margin_percentage}% margin. ⭕\n" + else: + res += f"The repository has {commits_30_days} commits in the last 30 days, which is way below the limit of {LIMIT_COMMITS_30_DAYS} commits, considering a {margin_percentage}% margin. ❌\n" + + nloc = get_lines_of_code(owner, repository) + if nloc >= LIMIT_NLOC: + res += f"The repository has over {LIMIT_NLOC} lines of code. ✅\n" + elif nloc >= LIMIT_NLOC * (1 - MARGIN): + res += f"The repository has {nloc} lines of code, which is close to the limit of {LIMIT_NLOC} lines of code, considering a {margin_percentage}% margin. ⭕\n" + else: + res += f"The repository has {nloc} lines of code, which is way below the limit of {LIMIT_NLOC} lines of code, considering a {margin_percentage}% margin. ❌\n" + + res += "\n" + + if any([stars < LIMIT_STARS * (1 - MARGIN), commits_30_days < LIMIT_COMMITS_30_DAYS * (1 - MARGIN), nloc < LIMIT_NLOC * (1 - MARGIN)]): + res += f"The repository {owner}/{repository} is not PICable. There are some requirements that are way below the requested limits. ❌\n" + elif all([stars >= LIMIT_STARS, commits_30_days >= LIMIT_COMMITS_30_DAYS, nloc >= LIMIT_NLOC]): + res += f"The repository {owner}/{repository} is PICable. ✅\n" + else: + res += f"The repository {owner}/{repository} is almost PICable. There are certain requirements which are almost met by this repository. Consult with a professor before proceeding. ⭕\n" + + return res \ No newline at end of file