mager-bench

Llama 3.3 70B × api-client

7.7

Class design + error handling + type hints + docs

correctness 8.0quality 6.0documentation 9.01706ms
$ cat api-client.prompt — what the model was asked
Write a Python class `APIClient` that wraps the `requests` library for a REST API. It should: (1) accept a base_url and optional api_key in __init__, (2) have a `get(path, params=None)` method and a `post(path, data)` method, (3) raise a custom `APIError` exception with the status code and message on non-2xx responses, (4) include type hints throughout, (5) have a complete docstring on the class and each public method. Show a usage example at the bottom.

run 1 of 1

7.7
correctness 8.0quality 6.0documentation 9.01706ms

# judge: Functionally correct with proper APIError subclass and docstrings, but lacks a requests.Session for connection reuse, has duplicated header logic, no timeout handling, and generic Dict types aren't parameterized.

$ cat llama-3.3-70b.api-client.r1.response
```python
import requests
from typing import Optional, Dict

class APIError(Exception):
    """Custom exception for API errors."""
    def __init__(self, status_code: int, message: str):
        self.status_code = status_code
        self.message = message
        super().__init__(f"API error {status_code}: {message}")

class APIClient:
    """
    A client for interacting with a REST API.

    Args:
    - base_url (str): The base URL of the API.
    - api_key (str, optional): The API key to use for authentication. Defaults to None.
    """
    def __init__(self, base_url: str, api_key: Optional[str] = None):
        self.base_url = base_url
        self.api_key = api_key

    def get(self, path: str, params: Optional[Dict[str, str]] = None) -> Dict:
        """
        Send a GET request to the API.

        Args:
        - path (str): The path of the API endpoint.
        - params (Dict[str, str], optional): The query parameters. Defaults to None.

        Returns:
        - Dict: The JSON response from the API.

        Raises:
        - APIError: If the API returns a non-2xx status code.
        """
        url = f"{self.base_url}{path}"
        headers = {"Authorization": f"Bearer {self.api_key}"} if self.api_key else {}
        response = requests.get(url, params=params, headers=headers)
        self._check_response(response)
        return response.json()

    def post(self, path: str, data: Dict) -> Dict:
        """
        Send a POST request to the API.

        Args:
        - path (str): The path of the API endpoint.
        - data (Dict): The JSON data to send in the request body.

        Returns:
        - Dict: The JSON response from the API.

        Raises:
        - APIError: If the API returns a non-2xx status code.
        """
        url = f"{self.base_url}{path}"
        headers = {"Authorization": f"Bearer {self.api_key}"} if self.api_key else {}
        response = requests.post(url, json=data, headers=headers)
        self._check_response(response)
        return response.json()

    def _check_response(self, response: requests.Response) -> None:
        """
        Check if the API response was successful.

        Args:
        - response (requests.Response): The API response.

        Raises:
        - APIError: If the API returns a non-2xx status code.
        """
        if not response.ok:
            raise APIError(response.status_code, response.text)


# Usage example:
if __name__ == "__main__":
    client = APIClient("https://jsonplaceholder.typicode.com")
    data = client.get("/posts/1")
    print(data)

    new_post = {"title": "My new post", "body": "This is my new post"}
    created_post = client.post("/posts", new_post)
    print(created_post)
```
In this code:

*   We define a custom `APIError` exception to handle non-2xx API responses.
*   The `APIClient` class has `get` and `post` methods for sending HTTP requests to the API.
*   The `_check_response` method checks if the API response was successful and raises an `APIError` if not.
*   In the usage example, we create an `APIClient` instance and use it to send GET and POST requests to a JSON placeholder API.