mager-bench

Llama 3.3 70B × api-client

7.0

Class design + error handling + type hints + docs

correctness 7.0quality 6.0documentation 8.01859ms
$ 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.0
correctness 7.0quality 6.0documentation 8.01859ms

# judge: Solid, working implementation with correct type hints and proper APIError subclass, but doesn't use requests.Session for connection reuse, uses naive string concatenation for URLs instead of urljoin, and lacks timeout/error handling for non-JSON responses.

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

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.

    Attributes:
        base_url (str): The base URL of the API.
        api_key (Optional[str]): The API key for authentication (optional).

    Methods:
        get(path: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: Send a GET request to the API.
        post(path: str, data: Dict[str, Any]) -> Dict[str, Any]: Send a POST request to the API.
    """
    def __init__(self, base_url: str, api_key: Optional[str] = None):
        """
        Initialize the API client.

        Args:
            base_url (str): The base URL of the API.
            api_key (Optional[str]): The API key for authentication (optional).
        """
        self.base_url = base_url
        self.api_key = api_key

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

        Args:
            path (str): The path of the API endpoint.
            params (Optional[Dict[str, Any]]): The query parameters (optional).

        Returns:
            Dict[str, Any]: The response data.

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

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

        Args:
            path (str): The path of the API endpoint.
            data (Dict[str, Any]): The request body data.

        Returns:
            Dict[str, Any]: The response data.

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

    def _check_response(self, response: requests.Response) -> None:
        """
        Check if the response status code is 2xx and raise an APIError if not.

        Args:
            response (requests.Response): The response object.
        """
        if not response.ok:
            raise APIError(response.status_code, response.text)

# Usage example:
if __name__ == "__main__":
    client = APIClient("https://example.com/api", "your_api_key")
    try:
        response = client.get("/users")
        print(response)
        client.post("/users", {"name": "John Doe", "email": "john@example.com"})
    except APIError as e:
        print(f"API Error {e.status_code}: {e.message}")
```

In this code:

*   We define a custom `APIError` exception class to represent API errors with a status code and message.
*   The `APIClient` class is initialized with a `base_url` and an optional `api_key` for authentication.
*   The `get` and `post` methods send GET and POST requests to the API, respectively, and return the response data as a dictionary.
*   The `_check_response` method checks if the response status code is 2xx and raises an `APIError` if not.
*   In the usage example, we create an instance of the `APIClient` class, send a GET request to retrieve users, and send a POST request to create a new user. We also catch and handle any `APIError` exceptions that may occur.