Pair Programming with ChatGPT

 

Earlier today I started work on a small admin project to help me organise my excessive collection of repositories on GitHub.

I wanted a list of my repositories, showing the name, url, description, stars and forks.

I decided to get ChatGPT to write the code for me.

In the conversation that follows, you can imagine an embodied ChatBot sitting next to me as we pair program. I'm the customer, ChatGPT is the programmer. If I'm not happy with the results, I ask my pair to change the code.

My part is in italics. Everything else came from ChatGPT.

As you'll see, there are a couple of wrinkles I didn't anticipate, but ChatGPT fixed them.

This took less time than I'd have taken to write the code, and it was much more fun. I recommend it.

Here's the session.

Write python to find the names of all my repositories on GitHub, My username is romilly.

You can use the GitHub API to retrieve the names of all your repositories. Here is the Python code to achieve that:

import requests

# Replace <username> with your GitHub username
username = "romilly"

# Make a GET request to the GitHub API to retrieve your repositories
response = requests.get(f"https://api.github.com/users/{username}/repos")

# Check if the response was successful
if response.status_code == 200:
    # Loop through the list of repositories and print their names
    for repo in response.json():
        print(repo["name"])
else:
    print("Failed to retrieve repositories")

This code uses the requests library to make a GET request to the GitHub API endpoint that retrieves your repositories. It then loops through the list of repositories in the response JSON and prints their names.

Modify that to output the name, url, description, stars and forks

Sure! Here's the modified code that retrieves and prints the name, URL, description, stars, and forks count of all your repositories:

import requests

# Replace <username> with your GitHub username
username = "romilly"

# Make a GET request to the GitHub API to retrieve your repositories
response = requests.get(f"https://api.github.com/users/{username}/repos")

# Check if the response was successful
if response.status_code == 200:
    # Loop through the list of repositories and print their details
    for repo in response.json():
        print(f"Name: {repo['name']}")
        print(f"URL: {repo['html_url']}")
        print(f"Description: {repo['description'] or 'No description available'}")
        print(f"Stars: {repo['stargazers_count']}")
        print(f"Forks: {repo['forks_count']}")
        print("="*50)
else:
    print("Failed to retrieve repositories")

This code uses the same requests library to make a GET request to the GitHub API endpoint that retrieves your repositories. It then loops through the list of repositories in the response JSON and prints their name, URL, description, stars count, and forks count. If the repository has no description, the code prints “No description available” instead. Finally, the code prints a line of equal signs (=) to separate each repository's details.

That only prints the fist few repositories. Modify the code to paginate though the full set.

You're right! By default, the GitHub API only returns the first 30 repositories, so we need to paginate through the full set to retrieve all your repositories. Here's the modified code that uses pagination:

import requests

# Replace <username> with your GitHub username
username = "romilly"

# Set the base URL for the GitHub API endpoint that retrieves your repositories
base_url = f"https://api.github.com/users/{username}/repos"

# Initialize the page number to 1
page = 1

# Loop through the pages of repositories
while True:
    # Make a GET request to the current page of the GitHub API endpoint
    response = requests.get(f"{base_url}?per_page=100&page={page}")

    # Check if the response was successful
    if response.status_code == 200:
        # If the response is empty, we have reached the last page of repositories
        if len(response.json()) == 0:
            break

        # Loop through the list of repositories on the current page and print their details
        for repo in response.json():
            print(f"Name: {repo['name']}")
            print(f"URL: {repo['html_url']}")
            print(f"Description: {repo['description'] or 'No description available'}")
            print(f"Stars: {repo['stargazers_count']}")
            print(f"Forks: {repo['forks_count']}")
            print("="*50)

        # Move to the next page
        page += 1
    else:
        print(f"Failed to retrieve repositories from page {page}")
        break

This code initialises the page number to 1 and loops through the pages of repositories using a while loop. It makes a GET request to the current page of the GitHub API endpoint with a per_page parameter of 100, which is the maximum number of repositories that the API allows to be returned per page. If the response is successful and not empty, the code loops through the list of repositories on the current page and prints their details. Finally, the code moves to the next page and repeats the process until there are no more repositories to retrieve. If the response is unsuccessful, the code prints an error message and breaks out of the loop.

What's the rate limit for GitHub API requests?

The rate limit for unauthenticated requests to the GitHub API is 60 requests per hour, while the rate limit for authenticated requests varies based on your authentication status and whether you are using a personal access token.

Here are the rate limits for authenticated requests:

Personal access token: 5,000 requests per hour
OAuth token: 5,000 requests per hour
OAuth token with public_repo or repo scope: 5,000 requests per hour
GitHub App installation token: 5,000 requests per hour
GitHub Actions token: 1,000 requests per hour

It's important to note that the rate limit is calculated on a per-IP address basis, so if multiple people are using the same IP address to make API requests, their combined rate limit will be shared.

To check your rate limit status, you can make a GET request to the following endpoint:

https://api.github.com/rate_limit

This endpoint returns a JSON object that contains information about your current rate limit status, including the number of remaining requests and the time at which the limit resets.

Modify the code to check the rate limit before each request. If the limit has been reached, delay the request until the limit resets.

Good idea! Here's the modified code that checks the rate limit before each request and delays the request until the limit resets if it has been reached:

import requests
import time

# Replace <username> with your GitHub username
username = "romilly"

# Set the base URL for the GitHub API endpoint that retrieves your repositories
base_url = f"https://api.github.com/users/{username}/repos"

# Initialize the page number to 1
page = 1

while True:
    # Check the rate limit status before making the request
    response = requests.get("https://api.github.com/rate_limit")
    if response.status_code != 200:
        print("Failed to retrieve rate limit status")
        break

    remaining_requests = response.json()["resources"]["core"]["remaining"]
    reset_timestamp = response.json()["resources"]["core"]["reset"]

    if remaining_requests == 0:
        # If we have reached the rate limit, delay the request until the limit resets
        delay_seconds = reset_timestamp - time.time() + 1
        print(f"Rate limit reached. Waiting for {delay_seconds:.2f} seconds...")
        time.sleep(delay_seconds)

    # Make a GET request to the current page of the GitHub API endpoint
    response = requests.get(f"{base_url}?per_page=100&page={page}")

    # Check if the response was successful
    if response.status_code == 200:
        # If the response is empty, we have reached the last page of repositories
        if len(response.json()) == 0:
            break

        # Loop through the list of repositories on the current page and print their details
        for repo in response.json():
            print(f"Name: {repo['name']}")
            print(f"URL: {repo['html_url']}")
            print(f"Description: {repo['description'] or 'No description available'}")
            print(f"Stars: {repo['stargazers_count']}")
            print(f"Forks: {repo['forks_count']}")
            print("="*50)

        # Move to the next page
        page += 1
    else:
        print(f"Failed to retrieve repositories from page {page}")
        break

This code first makes a GET request to the rate limit endpoint to retrieve the number of remaining requests and the time at which the limit resets. If we have reached the rate limit, the code calculates the number of seconds until the limit resets and waits for that amount of time using the time.sleep() function. After the delay, the code makes the GET request to the current page of the GitHub API endpoint as before. If the response is successful, the code loops through the list of repositories on the current page and prints their details. Finally, the code moves to the next page and repeats the process until there are no more repositories to retrieve. If the response is unsuccessful, the code prints an error message and breaks out of the loop.

What next?

I'm pretty happy with what ChatGPT did, but just like a real user I still want some changes - a database and a GUI to query it. I'll see if ChatGPT has time to do that and let you know.

I'll be posting on twitter as RAREblog.

If you found this interesting, please let others know: 

Comments

Popular posts from this blog

Controlling a Raspberry Pi Pico remotely using PySerial

Five steps to connect Jetson Nano and Arduino

Raspberry Pi Pico project 2 - MCP3008