improve code quality. improve final report readability.
This commit is contained in:
149
PICable.py
149
PICable.py
@@ -12,10 +12,9 @@ MARGIN = 0.1
|
|||||||
CLONE_DIR = "~/temp/PICable"
|
CLONE_DIR = "~/temp/PICable"
|
||||||
|
|
||||||
|
|
||||||
def get_stars_info(owner, repo, token):
|
def get_stars_info(owner, repository, request_headers):
|
||||||
headers = {"Authorization": f"token {token}"}
|
stars_url = f"https://api.github.com/repos/{owner}/{repository}"
|
||||||
stars_url = f"https://api.github.com/repos/{owner}/{repo}"
|
stars_response = requests.get(stars_url, headers=request_headers)
|
||||||
stars_response = requests.get(stars_url, headers=headers)
|
|
||||||
|
|
||||||
if stars_response.status_code != 200:
|
if stars_response.status_code != 200:
|
||||||
return -1
|
return -1
|
||||||
@@ -24,20 +23,21 @@ def get_stars_info(owner, repo, token):
|
|||||||
return stars
|
return stars
|
||||||
|
|
||||||
|
|
||||||
def get_commits_last_30_days(owner, repo, token):
|
def get_commits_last_30_days(owner, repository, request_headers):
|
||||||
headers = {"Authorization": f"token {token}"}
|
|
||||||
since = (datetime.now() - timedelta(days=30)).isoformat()
|
since = (datetime.now() - timedelta(days=30)).isoformat()
|
||||||
commits_url = f"https://api.github.com/repos/{owner}/{repo}/commits?since={since}"
|
commits_url = f"https://api.github.com/repos/{owner}/{repository}/commits?since={since}"
|
||||||
commits_response = requests.get(commits_url, headers=headers)
|
commits_response = requests.get(commits_url, headers=request_headers)
|
||||||
|
|
||||||
if commits_response.status_code != 200:
|
if commits_response.status_code != 200:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
if "link" in commits_response.headers:
|
if "link" in commits_response.headers:
|
||||||
page_count = int(commits_response.headers["link"].split(", ")[-1].split("; ")[0].split("page=")[1].split(">")[0])
|
page_count = int(
|
||||||
|
commits_response.headers["link"].split(", ")[-1].split("; ")[0].split("page=")[1].split(">")[0]
|
||||||
|
)
|
||||||
|
|
||||||
last_commits_url = f"{commits_url}&page={page_count}"
|
last_commits_url = f"{commits_url}&page={page_count}"
|
||||||
last_commits_response = requests.get(last_commits_url, headers=headers)
|
last_commits_response = requests.get(last_commits_url, headers=request_headers)
|
||||||
|
|
||||||
if last_commits_response.status_code != 200:
|
if last_commits_response.status_code != 200:
|
||||||
return -1
|
return -1
|
||||||
@@ -46,81 +46,92 @@ def get_commits_last_30_days(owner, repo, token):
|
|||||||
return len(commits_response.json())
|
return len(commits_response.json())
|
||||||
|
|
||||||
|
|
||||||
def get_lines_of_code(owner, repo):
|
def get_lines_of_code(owner, repository):
|
||||||
repo_url = f"https://github.com/{owner}/{repo}.git"
|
repo_url = f"https://github.com/{owner}/{repository}.git"
|
||||||
clone_dir = os.path.expanduser(f"{CLONE_DIR}/{repo}")
|
repository_clone_dir = os.path.expanduser(f"{CLONE_DIR}/{repository}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.run(["git", "clone", repo_url, clone_dir], check=True, stdout=sys.stdout, stderr=sys.stderr)
|
subprocess.run(
|
||||||
|
["git", "clone", repo_url, repository_clone_dir], check=True, stdout=sys.stdout, stderr=sys.stderr
|
||||||
|
)
|
||||||
except:
|
except:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
result = subprocess.run(["sloccount", clone_dir], capture_output=True, text=True, check=True)
|
result = subprocess.run(["sloccount", repository_clone_dir], capture_output=True, text=True, check=True)
|
||||||
for line in result.stdout.splitlines():
|
for line in result.stdout.splitlines():
|
||||||
if "Total Physical Source Lines of Code (SLOC)" in line:
|
if "Total Physical Source Lines of Code (SLOC)" in line:
|
||||||
loc = int(line.split()[8].replace(",", ""))
|
loc = int(line.split()[8].replace(",", ""))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
loc = 0
|
loc = 0
|
||||||
subprocess.run(["rm", "-rf", clone_dir], check=True)
|
subprocess.run(["rm", "-rf", repository_clone_dir], check=True)
|
||||||
return loc
|
return loc
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_repository(owner, repository, request_headers):
|
||||||
|
repository_url = f"https://api.github.com/repos/{owner}/{repository}"
|
||||||
|
repository_response = requests.get(repository_url, headers=request_headers)
|
||||||
|
return repository_response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
def PICable(owner, repository, token):
|
def PICable(owner, repository, token):
|
||||||
margin_percentage = round(MARGIN * 100)
|
margin_percentage = round(MARGIN * 100)
|
||||||
res = ""
|
request_headers = {"Authorization": f"token {token}"}
|
||||||
|
picable_report = ""
|
||||||
stars = get_stars_info(owner, repository, token)
|
|
||||||
|
|
||||||
if stars == -1:
|
|
||||||
return "The repository does not exist or the token is invalid. :x:"
|
|
||||||
|
|
||||||
if stars >= LIMIT_STARS:
|
|
||||||
res += f"The repository has at least {LIMIT_STARS} stars. :white_check_mark:\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. :warning:\n"
|
|
||||||
else:
|
|
||||||
res += f"The repository has {stars} stars, which is way below the limit of {LIMIT_STARS} stars, even if considering a {margin_percentage}% margin. :x:\n"
|
|
||||||
|
|
||||||
commits_30_days = get_commits_last_30_days(owner, repository, token)
|
|
||||||
|
|
||||||
if commits_30_days == -1:
|
|
||||||
return "The repository does not exist or the token is invalid. :x:"
|
|
||||||
|
|
||||||
if commits_30_days >= LIMIT_COMMITS_30_DAYS:
|
|
||||||
res += f"The repository has at least {LIMIT_COMMITS_30_DAYS} commits in the last 30 days. :white_check_mark:\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. :warning:\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, even if considering a {margin_percentage}% margin. :x:\n"
|
|
||||||
|
|
||||||
nloc = get_lines_of_code(owner, repository)
|
|
||||||
|
|
||||||
if nloc == -1:
|
|
||||||
return "The repository does not exist. :x:"
|
|
||||||
|
|
||||||
if nloc >= LIMIT_NLOC:
|
|
||||||
res += f"The repository has at least {LIMIT_NLOC} lines of code. :white_check_mark:\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. :warning:\n"
|
|
||||||
else:
|
|
||||||
res += f"The repository has {nloc} lines of code, which is way below the limit of {LIMIT_NLOC} lines of code, even if considering a {margin_percentage}% margin. :x:\n"
|
|
||||||
|
|
||||||
res += "\n"
|
|
||||||
|
|
||||||
repository_url = f"https://www.github.com/{owner}/{repository}"
|
repository_url = f"https://www.github.com/{owner}/{repository}"
|
||||||
|
|
||||||
if any(
|
if not is_valid_repository(owner, repository, request_headers):
|
||||||
[
|
return f"Invalid repository: {owner}/{repository} :x:"
|
||||||
stars < LIMIT_STARS * (1 - MARGIN),
|
|
||||||
commits_30_days < LIMIT_COMMITS_30_DAYS * (1 - MARGIN),
|
|
||||||
nloc < LIMIT_NLOC * (1 - MARGIN),
|
|
||||||
]
|
|
||||||
):
|
|
||||||
res += f"The repository {repository_url} is not PICable. There are some requirements that are way below the requested limits. :x:\n"
|
|
||||||
elif all([stars >= LIMIT_STARS, commits_30_days >= LIMIT_COMMITS_30_DAYS, nloc >= LIMIT_NLOC]):
|
|
||||||
res += f"The repository {repository_url} is PICable. :white_check_mark:\n"
|
|
||||||
else:
|
|
||||||
res += f"The repository {repository_url} is almost PICable. There are certain requirements which are almost met by this repository. Consult with a professor before proceeding. :warning:\n"
|
|
||||||
|
|
||||||
return res
|
stars = get_stars_info(owner, repository, request_headers)
|
||||||
|
if stars == -1:
|
||||||
|
return "Error fetching stars info. :x:"
|
||||||
|
|
||||||
|
if stars >= LIMIT_STARS:
|
||||||
|
picable_report += (
|
||||||
|
f"The repository has {stars} stars, which meets the requirement of {LIMIT_STARS}. :white_check_mark:\n"
|
||||||
|
)
|
||||||
|
elif stars >= LIMIT_STARS * (1 - MARGIN):
|
||||||
|
picable_report += f"The repository has {stars} stars, which is close to the requirement of {LIMIT_STARS}, considering a {margin_percentage}% margin. :warning:\n"
|
||||||
|
else:
|
||||||
|
picable_report += f"The repository has {stars} stars, which is way below the requirement of {LIMIT_STARS}, even if considering a {margin_percentage}% margin. :x:\n"
|
||||||
|
|
||||||
|
commits_30_days = get_commits_last_30_days(owner, repository, request_headers)
|
||||||
|
if commits_30_days == -1:
|
||||||
|
return "Error fetching commit info. :x:"
|
||||||
|
|
||||||
|
if commits_30_days >= LIMIT_COMMITS_30_DAYS:
|
||||||
|
picable_report += f"The repository has {commits_30_days} commits on the default branch in the last 30 days, which meets the requirement of {LIMIT_COMMITS_30_DAYS}. :white_check_mark:\n"
|
||||||
|
elif commits_30_days >= LIMIT_COMMITS_30_DAYS * (1 - MARGIN):
|
||||||
|
picable_report += f"The repository has {commits_30_days} commits on the default branch in the last 30 days, which is close to the requirement of {LIMIT_COMMITS_30_DAYS}, considering a {margin_percentage}% margin. :warning:\n"
|
||||||
|
else:
|
||||||
|
picable_report += f"The repository has {commits_30_days} commits on the default branch in the last 30 days, which is way below the requirement of {LIMIT_COMMITS_30_DAYS}, even if considering a {margin_percentage}% margin. :x:\n"
|
||||||
|
|
||||||
|
lines_of_code = get_lines_of_code(owner, repository)
|
||||||
|
if lines_of_code == -1:
|
||||||
|
return "Error fetching lines of code info. :x:"
|
||||||
|
|
||||||
|
if lines_of_code >= LIMIT_NLOC:
|
||||||
|
picable_report += f"The repository has {lines_of_code} lines of code, which meets the requirement of at least {LIMIT_NLOC}. :white_check_mark:\n"
|
||||||
|
elif lines_of_code >= LIMIT_NLOC * (1 - MARGIN):
|
||||||
|
picable_report += f"The repository has {lines_of_code} lines of code, which is close to the requirement of {LIMIT_NLOC}, considering a {margin_percentage}% margin. :warning:\n"
|
||||||
|
else:
|
||||||
|
picable_report += f"The repository has {lines_of_code} lines of code, which is way below the requirement of {LIMIT_NLOC}, even if considering a {margin_percentage}% margin. :x:\n"
|
||||||
|
|
||||||
|
picable_report += "\n"
|
||||||
|
|
||||||
|
if (
|
||||||
|
stars < LIMIT_STARS * (1 - MARGIN)
|
||||||
|
or commits_30_days < LIMIT_COMMITS_30_DAYS * (1 - MARGIN)
|
||||||
|
or lines_of_code < LIMIT_NLOC * (1 - MARGIN)
|
||||||
|
):
|
||||||
|
picable_report += f"The repository {repository_url} is not PICable. :x:\nThere is at least one requirement which is more than {margin_percentage}% below the requirement.\n"
|
||||||
|
elif all([stars >= LIMIT_STARS, commits_30_days >= LIMIT_COMMITS_30_DAYS, lines_of_code >= LIMIT_NLOC]):
|
||||||
|
picable_report += f"The repository {repository_url} is PICable. :white_check_mark:\n"
|
||||||
|
else:
|
||||||
|
picable_report += f"The repository {repository_url} is almost PICable. :warning:\nThere is at least one requirement which is below the requirement, but by less than {margin_percentage}%. Consult with a professor before proceeding.\n"
|
||||||
|
|
||||||
|
return picable_report
|
||||||
|
|
||||||
|
|
||||||
|
print(PICable("numpy", "numpy", "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"))
|
||||||
|
|||||||
Reference in New Issue
Block a user