Files
PICable/PICable.py
2025-02-23 22:27:35 +00:00

86 lines
4.0 KiB
Python

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