Metadata-Version: 2.5
Name: karni
Version: 0.3.1
Summary: Django + React framework that stays a versioned dependency, not a boilerplate: declare models and access, get the REST API, admin, permissions, tests and seed data. Built so AI coding agents (Claude Code, Cursor, Copilot) write only the domain code.
Project-URL: Homepage, https://github.com/cbsshekhawat18-lab/karni
Project-URL: Documentation, https://cbsshekhawat18-lab.github.io/karni/
Project-URL: Repository, https://github.com/cbsshekhawat18-lab/karni
Project-URL: Issues, https://github.com/cbsshekhawat18-lab/karni/issues
Project-URL: Changelog, https://github.com/cbsshekhawat18-lab/karni/tree/main/docs/migrations
Author-email: Chandrabhan Shekhawat <cbsshekhawat18@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: ai-agents,boilerplate,celery,claude-code,code-generation,copilot,cursor,django,django-rest-framework,framework,full-stack,openapi,react,scaffolding
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.2
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: celery[redis]>=5.3
Requires-Dist: django-celery-beat>=2.6
Requires-Dist: django-celery-results>=2.5
Requires-Dist: django-cors-headers>=4.4
Requires-Dist: django-environ>=0.11
Requires-Dist: django-filter>=24.2
Requires-Dist: django-structlog>=8.0
Requires-Dist: django-unfold<0.111,>=0.110
Requires-Dist: django<5.3,>=5.2.8
Requires-Dist: djangorestframework-simplejwt<6,>=5.4
Requires-Dist: djangorestframework>=3.15
Requires-Dist: drf-spectacular>=0.27
Requires-Dist: factory-boy>=3.3
Requires-Dist: openpyxl>=3.1
Requires-Dist: pydantic>=2
Requires-Dist: redis>=5
Requires-Dist: structlog>=24.1
Provides-Extra: 2fa
Requires-Dist: django-otp>=1.5; extra == '2fa'
Provides-Extra: images
Requires-Dist: pillow>=10.3; extra == 'images'
Provides-Extra: s3
Requires-Dist: boto3>=1.34; extra == 's3'
Requires-Dist: django-storages[s3]>=1.14; extra == 's3'
Provides-Extra: sentry
Requires-Dist: sentry-sdk>=2.0; extra == 'sentry'
Provides-Extra: social
Requires-Dist: django-allauth>=65.3; extra == 'social'
Description-Content-Type: text/markdown

# karni

Batteries-included Django glue: one call assembles the settings every
Django + DRF + Celery project repeats, with production-safe defaults, startup
validation, and an escape hatch for every single value. On top of the
settings core it ships the three batteries every project rewrites:

- **karni.accounts** — email-based swappable user, JWT or session auth
  endpoints, verified-email / password-reset / email-change flows, roles,
  optional TOTP 2FA and social login ([docs](https://cbsshekhawat18-lab.github.io/karni/accounts/))
- **karni.api** — `class EventViewSet(BaseViewSet): model = Event` gives
  CRUD + filtering + search + expansion + OpenAPI, auto-routed
  ([docs](https://cbsshekhawat18-lab.github.io/karni/api/))
- **karni.admin** — zero-config django-unfold admin: every model registered
  with derived columns, filters, search and soft-delete handling
  ([docs](https://cbsshekhawat18-lab.github.io/karni/admin/))

```bash
pip install karni            # core
pip install 'karni[s3]'      # + S3-compatible storage (django-storages, boto3)
pip install 'karni[images]'  # + thumbnailing (Pillow)
pip install 'karni[sentry]'  # + Sentry (sentry-sdk)
pip install 'karni[social]'  # + social login (django-allauth)
pip install 'karni[2fa]'     # + TOTP two-factor auth (django-otp)
```

## A whole settings.py

```python
from karni.conf import karni_settings

karni_settings(globals())

# Project-specific settings below — anything defined here wins.
INSTALLED_APPS += [
    # "myapp",
]
```

That call configures: `INSTALLED_APPS`, middleware, Postgres from
`DATABASE_URL`, Redis cache, DRF (pagination, filter backends, throttling,
drf-spectacular schema), Celery (+ django-celery-beat, django-celery-results),
file storage (local or S3-compatible), structlog logging (console in dev,
JSON in prod), security headers, CORS, and optional Sentry. At startup the
merged settings are validated by a Pydantic model and every bad value is
reported at once (`KARNI_VALIDATE = False` skips this).

## Overriding defaults

`karni_settings()` uses **setdefault semantics** — it never overwrites a name
you already defined. Three layers, strongest first:

1. **Assign after the call** — always wins:
   `REST_FRAMEWORK["PAGE_SIZE"] = 20`
2. **Define before the call** — never touched. For `INSTALLED_APPS` and
   `MIDDLEWARE`, Karni appends its missing entries after yours instead of
   replacing the list.
3. **Keyword overrides** — `karni_settings(globals(), CELERY_TASK_TIME_LIMIT=60)`
   replaces the Karni default (whole-value replacement) but still yields to
   names defined in the module.

Most defaults also read environment variables (via django-environ), so the
same image runs in dev and prod with only a `.env` change.

## Profiles

`DJANGO_ENV=dev` (default) or `DJANGO_ENV=prod` — or force one with
`karni_settings(globals(), env_name="prod")`.

| | dev | prod |
|---|---|---|
| `DEBUG` | `True` | `False` |
| `ALLOWED_HOSTS` | `["*"]` | required, from env |
| `SECRET_KEY` | insecure default allowed | required, validated |
| Logging | colorized console (structlog) | JSON lines (structlog) |
| CORS | allow all origins | `CORS_ALLOWED_ORIGINS` only |
| Security headers | off | HSTS, SSL redirect, secure cookies, nosniff, `X-Frame-Options: DENY` |

## Environment variables

| Variable | Default | Meaning |
|---|---|---|
| `DJANGO_ENV` | `dev` | settings profile: `dev` or `prod` |
| `SECRET_KEY` | insecure dev key | **required in prod** (validation fails otherwise) |
| `DEBUG` | dev `True` / prod `False` | debug mode |
| `ALLOWED_HOSTS` | dev `*` / prod empty | comma-separated; **required in prod** |
| `DATABASE_URL` | `postgres://karni:karni@db:5432/karni` | database DSN |
| `REDIS_URL` | `redis://redis:6379/0` | cache + Celery broker |
| `CORS_ALLOWED_ORIGINS` | empty | comma-separated origins |
| `KARNI_PAGE_SIZE` | `50` | DRF default page size |
| `THROTTLE_ANON` / `THROTTLE_USER` | `100/min` / `1000/min` | DRF throttle rates |
| `PROJECT_NAME` | `karni-project` | API title, Celery app name |
| `KARNI_STORAGE` | `local` | `local` or `s3` |
| `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_STORAGE_BUCKET_NAME`, `AWS_S3_ENDPOINT_URL`, `AWS_S3_REGION_NAME` | empty | S3-compatible storage (MinIO/R2 via endpoint URL) |
| `SENTRY_DSN` | empty | Sentry disabled when empty |
| `SENTRY_TRACES_SAMPLE_RATE` | `0.0` | Sentry tracing sample rate |
| `MEDIA_ROOT` / `STATIC_ROOT` | `/data/media` / `/data/static` | file roots |

## Celery

```python
# config/celery.py
from karni.celery import create_celery_app

app = create_celery_app()
```

Broker, django-db results, database beat scheduler and task autodiscovery are
configured from the `CELERY_*` settings that `karni_settings()` provided.
Periodic tasks declared with `karni.schedule.every()` / `cron()` in
`<app>/schedules.py` are merged into the beat schedule
([docs/scheduling.md](https://cbsshekhawat18-lab.github.io/karni/scheduling/)). Model lifecycle listeners
live in `<app>/listeners.py` ([docs/events.md](https://cbsshekhawat18-lab.github.io/karni/events/)).
`manage.py karni_routes` and `manage.py karni_schedules` list every URL and
every schedule (`--json` for agents).

## Health checks

```python
# config/urls.py
path("health/", include("karni.health.urls")),
```

`/health/` is a no-I/O liveness probe; `/health/ready/` runs the checks in
`KARNI_HEALTH_CHECKS` (Postgres, Redis, Celery by default — a list of dotted
paths you can extend or replace) and returns 200 or 503 with per-check detail.

## Storage & thumbnails

`KARNI_STORAGE=s3` switches the default storage to
`karni.storage.S3Storage` (S3-compatible, endpoint-aware); anything else uses
local `FileSystemStorage`. `karni.storage.thumbnails.make_thumbnail()`
produces aspect-preserving thumbnails; swap the implementation via the
`KARNI_THUMBNAILER` dotted-path setting.

## Development

```bash
cd packages/karni
pip install -e . --group dev
pytest
ruff check .
```
