Metadata-Version: 2.4
Name: creatine
Version: 0.1.0
Summary: A lightweight Python web framework with WSGI and ASGI support.
Author: Fazliddin
License: MIT
Project-URL: Homepage, https://github.com/fazliddinio/creatine
Project-URL: Repository, https://github.com/fazliddinio/creatine
Project-URL: Issues, https://github.com/fazliddinio/creatine/issues
Keywords: web,framework,wsgi,asgi,http
Classifier: Development Status :: 3 - Alpha
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: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Jinja2>=3.1
Requires-Dist: parse>=1.20
Requires-Dist: requests>=2.30
Requires-Dist: requests-wsgi-adapter>=0.4
Requires-Dist: WebOb>=1.8
Requires-Dist: whitenoise>=6.5
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: gunicorn>=22.0; extra == "dev"
Requires-Dist: uvicorn>=0.30; extra == "dev"
Dynamic: license-file

# Creatine

A lightweight Python web framework with WSGI and ASGI support.

## Installation

```bash
pip install creatine
```

For development:

```bash
pip install creatine[dev]
```

## Quick Start

```python
from creatine import Creatine

app = Creatine()


@app.route("/")
def home(req, resp):
    resp.text = "Hello, World!"


@app.route("/greeting/{name}")
def greeting(req, resp, name):
    resp.text = f"Hello, {name}"


@app.route("/book")
class BookResource:
    def get(self, req, resp):
        resp.text = "Books Page"

    def post(self, req, resp):
        resp.text = "Book created"


@app.route("/json")
def json_handler(req, resp):
    resp.json = {"message": "hello"}


@app.route("/template")
def template_handler(req, resp):
    resp.html = app.template("index.html", context={"title": "Hello"})
```

## Running the Server

```bash
# Built-in dev server
creatine runserver app:app

# With Gunicorn (WSGI)
gunicorn app:app

# With Uvicorn (ASGI)
uvicorn app:asgi_app
```

## ASGI & Async Handlers

Creatine supports both sync and async handlers when running under ASGI:

```python
app = Creatine()

asgi_app = app.as_asgi()

@app.route("/async")
async def async_handler(req, resp):
    resp.json = {"async": True}
```

## Middleware

```python
from creatine import Middleware
from creatine.log import LoggingMiddleware

# Built-in request logging
app.add_middleware(LoggingMiddleware)

# Custom middleware
class AuthMiddleware(Middleware):
    def process_request(self, req):
        print(f"Auth check: {req.url}")

    def process_response(self, req, resp):
        print(f"Completed: {resp.status_code}")

app.add_middleware(AuthMiddleware)
```

## ORM

Built-in SQLite ORM for simple data persistence:

```python
from creatine import Database, Table, Column, ForeignKey

db = Database("./app.db")

class Author(Table):
    name = Column(str)
    age = Column(int)

class Book(Table):
    title = Column(str)
    author = ForeignKey(Author)

db.create(Author)
db.create(Book)

author = Author(name="Jane", age=30)
db.save(author)
db.update(author)
db.delete(Author, id=1)
```

## Features

- WSGI and ASGI compatible
- Async handler support
- Parameterized and basic routing
- Class-based and function-based handlers
- Built-in SQLite ORM with foreign keys
- Jinja2 templates
- Static files via WhiteNoise
- Middleware pipeline with built-in logging
- Custom exception handlers
- Test client (based on Requests)
- CLI (`creatine runserver`)
- GitHub Actions CI with pytest and mypy

## Tests

```bash
pytest
```

## Project Structure

```
creatine/
├── __init__.py      # Package exports and version
├── __main__.py      # CLI entry point
├── api.py           # Core Creatine application class
├── asgi.py          # ASGI adapter
├── exceptions.py    # HTTPError
├── log.py           # Logging middleware
├── middleware.py     # Middleware base class
├── orm.py           # SQLite ORM
├── response.py      # Response wrapper
├── route.py         # Route matching and dispatch
└── utils.py         # Static file and test helpers
```

## License

MIT
