Metadata-Version: 2.4
Name: astra-client
Version: 0.1.5
Summary: Async HTTP client with clean API and automatic error handling
Project-URL: Homepage, https://github.com/ndugram/astrahttp
Project-URL: Repository, https://github.com/ndugram/astrahttp
Project-URL: Issues, https://github.com/ndugram/astrahttp/issues
Author-email: NEFORCEO <n7for8572@gmail.com>
License: MIT
License-File: LICENSE
Keywords: async,asyncio,client,http,httpx
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.13.3
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Provides-Extra: http2
Requires-Dist: httpx[http2]>=0.28.1; extra == 'http2'
Description-Content-Type: text/markdown

<div align="center">

# astra-client

**Async HTTP client for Python with clean API and automatic error handling**

[![PyPI version](https://badge.fury.io/py/astra-client.svg)](https://pypi.org/project/astra-client)
[![Python](https://img.shields.io/pypi/pyversions/astra-client)](https://pypi.org/project/astra-client)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![CI](https://github.com/ndugram/astrahttp/actions/workflows/release.yml/badge.svg)](https://github.com/ndugram/astrahttp/actions)

</div>

---

## Key Features

- **Zero-boilerplate URLs** — write `"google.com"` instead of `"https://google.com"`
- **Automatic error handling** — 4xx/5xx responses raise typed exceptions, no manual checks needed
- **Async context managers** — clean resource lifecycle with `async with`
- **Full HTTP verb coverage** — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
- **Typed exception hierarchy** — catch exactly what you need, from `NotFoundError` to `AstraHttpError`
- **Python 3.10+** — modern type hints throughout (`X | None`, `dict[str, Any]`)

---

## Installation

```bash
pip install astra-client
```

```bash
uv add astra-client
```

---

## Quick Start

```python
import asyncio
import astra

async def main():
    async with astra.ClientSession() as session:
        async with session.get("httpbin.org/get") as response:
            print(response.status)
            data = await response.json()
            print(data)

asyncio.run(main())
```

> No scheme? No problem. `astra-client` automatically prepends `https://` if missing.

### POST with JSON

```python
async with astra.ClientSession() as session:
    async with session.post(
        "httpbin.org/post",
        json={"name": "astra", "fast": True},
    ) as response:
        print(await response.json())
```

### Custom headers & base URL

```python
async with astra.ClientSession(
    base_url="https://api.example.com",
    headers={"Authorization": "Bearer TOKEN"},
    timeout=10.0,
) as session:
    async with session.get("/users/me") as response:
        user = await response.json()
```

---

## Error Handling

`astra-client` raises typed exceptions automatically — no need to call `raise_for_status()` manually.

```python
import astra

async def fetch():
    try:
        async with astra.ClientSession() as session:
            async with session.get("httpbin.org/status/404") as response:
                ...
    except astra.NotFoundError:
        print("Resource not found")
    except astra.UnauthorizedError:
        print("Invalid credentials")
    except astra.TooManyRequestsError:
        print("Rate limit hit — slow down")
    except astra.TimeoutError:
        print("Request timed out")
    except astra.ConnectionError:
        print("Could not reach the server")
    except astra.AstraHttpError as e:
        print(f"Unexpected error: {e}")
```

### Exception Hierarchy

```
AstraHttpError
├── NetworkError
│   ├── ConnectionError
│   ├── TimeoutError
│   ├── TooManyRedirectsError
│   └── InvalidURLError
└── HTTPStatusError
    ├── ClientError          (4xx)
    │   ├── BadRequestError          400
    │   ├── UnauthorizedError        401
    │   ├── ForbiddenError           403
    │   ├── NotFoundError            404
    │   ├── MethodNotAllowedError    405
    │   ├── UnprocessableEntityError 422
    │   └── TooManyRequestsError     429
    └── ServerError          (5xx)
        ├── InternalServerError      500
        ├── BadGatewayError          502
        ├── ServiceUnavailableError  503
        └── GatewayTimeoutError      504
```

---

## Response API

```python
async with session.get("httpbin.org/json") as response:
    response.status        # int — HTTP status code
    response.headers       # httpx.Headers

    text = await response.text()   # str
    data = await response.json()   # Any
    raw  = await response.read()   # bytes
```

---

## Requirements

- Python 3.10+
- [httpx](https://www.python-httpx.org/) >= 0.28.1

---

## License

`astra-client` is released under the [MIT License](LICENSE).
