PyGithub authentication
GitHub requires authentication for almost every useful operation. A personal access token with repo scope covers everything you need: reading PRs, downloading diffs, and writing reviews. PyGithub wraps the REST API in a clean Python client that handles auth headers and JSON parsing for you.
import os
from github import Github
def _client() -> Github:
token = os.getenv("GITHUB_TOKEN")
if not token:
raise RuntimeError(
"GITHUB_TOKEN is not set. Add it to .env to call the GitHub API."
)
return Github(token)The client is lazy. It reads GITHUB_TOKEN from the environment and constructs a Github object on demand. Fail loudly when the token is missing, because the alternative is a confusing permission error deep inside PyGithub.
from github import GithubException
from models import PRDiff
def get_pr_diff(owner: str, repo: str, number: int) -> PRDiff:
"""Fetch a PR's unified diff plus its list of changed files."""
gh = _client()
try:
repository = gh.get_repo(f"{owner}/{repo}")
pr = repository.get_pull(number)
except GithubException as exc:
raise RuntimeError(f"GitHub error fetching PR: {exc.data}") from exc
import httpx
headers = {
"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}",
"Accept": "application/vnd.github.v3.diff",
}
resp = httpx.get(pr.url, headers=headers, timeout=30.0)
resp.raise_for_status()
diff_text = resp.text
changed = [f.filename for f in pr.get_files()]
return PRDiff(
owner=owner, repo=repo, pr_number=number,
title=pr.title, diff=diff_text, changed_files=changed,
)PyGithub gives you the PR metadata cleanly, but the unified diff requires a separate request with a special Accept header. Setting application/vnd.github.v3.diff returns the raw patch text instead of JSON.
PyGithub returns PR objects as JSON. GitHub serves the unified diff only when you set the vnd.github.v3.diff media type in the Accept header. PyGithub does not expose a one-liner for that, so you fall back to a plain httpx request using the PR url the client already resolved for you.
Quiz: Quiz
Loading practice…