Can ChatGPT code like a pro?

I've been experimenting with the code generation capabilities of ChatGPT, and I'm blown away.

As a test of its capabilities I decided to ask it to write a generic version of some code I've used, over and over, in slightly different forms, in real applications.

The Problem

The code implements a Throttler - a class that wraps something that makes requests and makes sure that requests are not made too often.

Lots of APIs apply rate limits to requests, and this code makes it easy to enforce those limits within your application.

A coding session with ChatGPT

Here'es the session I had with ChatGPT. My instructions are in italics. Everything else - code, comments, and explanations - was written by ChatGPT in response.

Write Python to create an Abstract Class called Requester. It should have a single abstract method called request that takes an argument called command. Add docstring comments.

Here is the Python code to create an Abstract Class called Requester with a single abstract method called request that takes an argument called command:

from abc import ABC, abstractmethod

class Requester(ABC):
    """
    Abstract class for requesting commands.
    """

    @abstractmethod
    def request(self, command):
        """
        Abstract method for requesting a command.

        Args:
            command (str): The command to request.

        Returns:
            None
        """
        pass

In this code, we import the ABC (Abstract Base Class) module from the abc package. Then, we define the Requester class as an abstract class that inherits from ABC. We also define the single abstract method called request, which takes an argument called command. The docstring comments provide information about the class and the abstract method, including the arguments and return values.

Write code and docstring comments for a subclass called MockRequester which stores each request in a list. The list should be initialised in the constructor init method.

Here is the Python code to create a subclass called MockRequester which stores each request in a list:

class MockRequester(Requester):
    """
    Subclass of Requester that stores each request in a list.
    """

    def __init__(self):
        """
        Constructor for MockRequester that initializes an empty list to store the requests.
        """
        self.requests = []

    def request(self, command):
        """
        Method to request a command and store it in the list of requests.

        Args:
            command (str): The command to request.

        Returns:
            None
        """
        self.requests.append(command)

In this code, we define the MockRequester class as a subclass of Requester. We also define the constructor method init which initializes an empty list to store the requests. The request method is also defined and it takes the command argument, which it stores in the list of requests using the append method. The docstring comments provide information about the class and methods, including the arguments and return values.

Now add a Throttler class subclass of Requester which takes a requester and a gap (a number of seconds) in its constructor. The Throttler should make sure that successive requests are separated by the sepcified number of seconds. As before, add docstring comments and add type hints.

Here is the Python code to create a Throttler class, a subclass of Requester, which takes a requester and a gap (a number of seconds) in its constructor:

import time

class Throttler(Requester):
    """
    Subclass of Requester that adds throttling functionality to limit the rate of requests.

    Args:
        requester (Requester): The requester object that Throttler will throttle.
        gap (float): The number of seconds to wait between each request.
    """

    def __init__(self, requester: Requester, gap: float):
        """
        Constructor for Throttler that initializes the requester and the gap.

        Args:
            requester (Requester): The requester object that Throttler will throttle.
            gap (float): The number of seconds to wait between each request.
        """
        self.requester = requester
        self.gap = gap
        self.last_request_time = None

    def request(self, command: str) -> None:
        """
        Method to request a command with throttling between requests.

        Args:
            command (str): The command to request.

        Returns:
            None
        """
        if self.last_request_time is not None:
            time_since_last_request = time.time() - self.last_request_time
            time_to_wait = self.gap - time_since_last_request
            if time_to_wait > 0:
                time.sleep(time_to_wait)

        self.requester.request(command)
        self.last_request_time = time.time()

In this code, we define the Throttler class as a subclass of Requester. We also define the constructor method init which takes a requester object and a gap parameter. The request method is also defined which makes sure that the time gap between successive requests is at least the specified gap in seconds, before forwarding the request to the requester object. The docstring comments provide information about the class and methods, including the arguments and return values, as well as the types of the arguments.

Write a unit test using the unit test framework, a Throttler and the MockThrottler class to verify that the delay is working correctly. The test should take less than one tenth of a second to run. Add comments for the test.

Here is the Python code for a unit test that uses the Throttler and MockRequester classes to verify that the delay is working correctly:

import unittest

class TestThrottler(unittest.TestCase):
    """
    Unit test for Throttler class.
    """

    def test_throttling(self):
        """
        Test that the Throttler enforces the specified delay between requests.
        """
        mock_requester = MockRequester()
        throttler = Throttler(mock_requester, 0.1)

        # Send 3 requests and verify that the delay between requests is at least 0.1 seconds
        start_time = time.time()
        throttler.request("command 1")
        throttler.request("command 2")
        throttler.request("command 3")
        end_time = time.time()

        # Verify that the requests were received in the correct order
        self.assertEqual(mock_requester.requests, ["command 1", "command 2", "command 3"])

        # Verify that the total time taken is at least 0.2 seconds (2 x 0.1 seconds)
        self.assertGreaterEqual(end_time - start_time, 0.2)

In this code, we define a unit test case TestThrottler that tests the Throttler class. The test method test_throttling creates a MockRequester object and a Throttler object with a delay of 0.1 seconds. It then sends 3 requests using the Throttler and verifies that the requests were received in the correct order. Finally, it checks that the total time taken is at least 0.2 seconds (2 x 0.1 seconds) to verify that the delay is working correctly. The comments provide information about the purpose of the test and what it is testing.

Conclusion

I can't believe the level of skill that ChatGPT is showing. 

Not only does it do a great job at coding, but it correctly worked out what I really wanted when I mistakenly asked it to use a MockThrottler instead of a MockRequester in the test!

I've been using it for coding tasks for the last three days and I've created documented, tested code about five times faster than I would on my own.

Try it yourself.

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