Metadata-Version: 2.4
Name: tradekart-cloud
Version: 0.1.1
Summary: AWS utilities for TradeKart - Cloud
Author-email: Vikalp Varshney <vikalp@tradekart_gmail.com>, Siddhant Varshney <siddhant@tradekart_gmail.com>
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: boto3>=1.34.0
Requires-Dist: aioboto3>=12.4.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: moto[dynamodb,s3,secretsmanager,server]>=5.0.0; extra == "dev"
Requires-Dist: ruff>=0.6.0; extra == "dev"

# tradekart-cloud

A small toolbox that lets any TradeKart app talk to AWS (S3 file storage, DynamoDB database) without dealing with AWS's raw SDK every time.

## System Design

![TradeKart Cloud AWS System Design](<system-design/TradeKart Cloud AWS System Design(1).png>)

## Why use this instead of talking to AWS directly?

- **One remote control, not five.** Instead of every script/service writing its own `boto3.client(...)` setup, you just do `AWS().s3` or `AWS().dynamodb` and it's ready to use.
- **Errors you can actually read.** If AWS fails, you don't get a wall of a cryptic traceback — you get one clean error (`TradeKartCloudError`) that tells you exactly what failed, on which bucket/table, and why.
- **Won't freeze your app.** It comes in two flavors — a normal (sync) version for scripts and CLI tools, and an async version for use inside `async def` code (like FastAPI routes). Using the wrong one inside a live web server can freeze it for every user until that one AWS call finishes — this package gives you the right tool for each case so that doesn't happen.
- **Change AWS settings in one place.** Region, AWS profile, or a custom endpoint (for local testing) — all live in one small `AWSConfig`, not scattered across the codebase.

## Install

```bash
pip install -e /path/to/tradekart-cloud       # normal use
pip install -e "/path/to/tradekart-cloud[dev]"  # if you also want to run its tests
```

## Quick start

```python
from cloud import AWS, AWSConfig
from cloud.storage.s3 import UploadFileRequest
from cloud.database.dynamodb import PutItemRequest

aws = AWS(AWSConfig(region_name='ap-south-1'))

# Upload a file to S3
aws.s3.upload_file(
    UploadFileRequest(
        bucket_name='my-bucket', object_key='orders/1.json', file_path='1.json'
    )
)

# Write a row to DynamoDB
aws.dynamodb.put_item(
    PutItemRequest(
        table_name='orders', item={'PK': 'USER#1', 'SK': 'ORDER#1', 'status': 'PLACED'}
    )
)
```

### Inside an `async def` function (FastAPI, etc.)

Use the `_async` versions so AWS calls run in the background instead of blocking the whole server:

```python
from cloud import AWS, AWSConfig
from cloud.storage.s3 import UploadFileRequest

aws = AWS(AWSConfig(region_name='ap-south-1'))


async def save_order_audit(payload: dict) -> None:
    await aws.s3_async.upload_file(
        UploadFileRequest(
            bucket_name='audit-bucket', object_key='event.json', file_path='event.json'
        )
    )
```

**Rule of thumb:** in a plain script or CLI tool, use `aws.s3` / `aws.dynamodb`. Inside `async def` route handlers, use `aws.s3_async` / `aws.dynamodb_async`.

## What's inside (folder by folder)

| Folder | What it's for |
|---|---|
| `cloud/config` | AWS settings — region, profile, optional custom endpoint. |
| `cloud/session` | Opens the connection to AWS (one sync version, one async version). |
| `cloud/clients` | Shared base logic every AWS client uses — mainly turning AWS errors into `TradeKartCloudError`. |
| `cloud/storage/s3` | Upload, download, delete, and generate a temporary shareable link for S3 files. |
| `cloud/database/dynamodb` | Put, get, update, delete, and query rows in DynamoDB. |
| `cloud/exceptions` | The one error type (`TradeKartCloudError`) all AWS failures come back as. |
| `tests/` | Test suite (uses `moto` to fake AWS, so no real AWS account or cost is needed). |

## Error handling

Every AWS call can raise `TradeKartCloudError`. It always tells you:

```python
from cloud.exceptions import TradeKartCloudError

try:
    aws.s3.upload_file(request)
except TradeKartCloudError as e:
    print(e.service)  # 's3'
    print(e.operation)  # 'upload_file'
    print(e.error_code)  # AWS's own error code, e.g. 'NoSuchBucket'
    print(e.message)  # a plain-English description
```

## Running the tests

```bash
pip install -e ".[dev]"
pytest
```

No real AWS account is needed — tests run against `moto`, a fake in-memory AWS. The async tests spin up a small local `moto` server automatically (needed because the async AWS library talks over a different connection than the sync one).
