Skip to content

Instantly share code, notes, and snippets.

@Secozzi
Created May 21, 2021 09:17
Show Gist options
  • Save Secozzi/55fd57a5c74278a96d3087da7aa2c55d to your computer and use it in GitHub Desktop.
Save Secozzi/55fd57a5c74278a96d3087da7aa2c55d to your computer and use it in GitHub Desktop.
Quickly get info on Github repository from the REST API
from __future__ import annotations
from datetime import datetime, timezone
from typing import Tuple, List
from rich.table import Table
from rich import print
from rich.box import Box
import requests
import sys
import re
ROUNDED_BORDER: Box = Box(
"""\
╭──╮
│ │
│ │
│ │
│ │
│ │
│ │
╰──╯
"""
)
def LINK(owner, repo):
return f"https://api.github.com/repos/{owner}/{repo}"
def get_link(url) -> Tuple[str, str] | List[str]:
is_link = re.compile(r"^(git(hub)?|https?)")
is_git_path = re.compile(r"^[a-zA-Z0-9\-_.]+/[a-zA-Z0-9\-_.]+")
git_url_regex = re.compile(r"^(https|git)?(://|@)?([^/:]+)[/:](?P<owner>[^/:]+)/(?P<name>.+)(.git)?$")
is_git_repo = re.compile(r"((.git)|/)$")
if is_link.match(url):
if is_git_path.match(url):
return url.split("/")[:2]
match = git_url_regex.match(url)
if not match:
raise Exception("Invalid path")
name = match.group("name").split("/")[0]
name = is_git_repo.sub("", name)
owner = match.group("owner")
return owner, name
else:
if url.count("/") > 0:
return url.split("/")[:2]
raise Exception("Link/path must contain both user and repo")
def humanize_time(time_str):
if not time_str:
return "null"
now = datetime.now()
date = datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%SZ")
date = date.replace(tzinfo=timezone.utc)
diff = int(now.timestamp() - date.timestamp())
times = [
1, 60, 3600, 86400, 604800, 2629746, 31556925
]
times_str = [
"Second", "Minute", "Hour", "Day", "Week", "Month", "Year"
]
temp = [diff // t for t in times][::-1]
for i, t in enumerate(temp):
if t != 0:
return f"{t} {times_str[6-i]}{'' if t == 1 else 's'} ago"
def human_size(bytes, units=None):
if units is None:
units = [' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']
return f"{round(bytes, 2)} " + units[0] if bytes < 1024 else human_size(bytes / 1024, units[1:])
url = sys.argv[1]
token = "ACCESS_TOKEN"
query_url = LINK(*get_link(url))
headers = {"Authorization": f"token {token}"}
r = requests.get(query_url, headers=headers)
data = r.json()
grid = Table(
show_header=False,
header_style=None,
box=ROUNDED_BORDER,
title=data["full_name"]
)
owner = data['owner']['login']
grid.add_row(
f"Owner - [blue][link https://github.com/{owner}]{owner}[/] ",
f"Size - [#3685B5]{human_size(data['size']*1024)}[/] ",
f"Created at - [#A9E190]{humanize_time(data['created_at'])}[/] ",
)
grid.add_row(
f"URL - [blue][link {data['html_url']}]Link[/] ",
f"Stars - [magenta]{data['stargazers_count']}[/] ",
f"Updated at - [#A9E190]{humanize_time(data['updated_at'])}[/] ",
)
grid.add_row(
f"License - [blue][link {data['license']['url']}]{data['license']['key']}[/] ",
f"Forks - [magenta]{data['forks']}[/] ",
f"Pushed at - [#A9E190]{humanize_time(data['pushed_at'])}[/] ",
)
grid.add_row(
f"Language - [green]{data['language']}[/] ",
f"Watchers - [magenta]{data['watchers_count']}[/] ",
f"Open issues - [magenta]{data['open_issues']}[/] "
)
print(grid)

Example: > gitinfo.py microsoft/vscode

Output:

                                 microsoft/vscode
╭────────────────────────────────────────────────────────────────────────────────╮
│ Owner    - microsoft     Size     - 362.93 MB    Created at  - 5 Years ago     │
│ URL      - Link          Stars    - 116125       Updated at  - 11 Minutes ago  │
│ License  - mit           Forks    - 18946        Pushed at   - 25 Minutes ago  │
│ Language - TypeScript    Watchers - 116125       Open issues - 5353            │
╰────────────────────────────────────────────────────────────────────────────────╯

> gitinfo.py https://github.com/microsoft/vscode and > gitinfo.py https://github.com/microsoft/vscode.git would yield the same result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment