tsuno


Nametsuno JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryHigh-performance WSGI/ASGI server for Python, powered by Rust
upload_time2025-10-21 11:35:08
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseNone
keywords wsgi asgi server rust async http2 fastapi flask django starlette tsuno
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 🦄 Tsuno

**High-performance WSGI/ASGI server powered by Rust**

![Python Version](https://img.shields.io/badge/python-3.11+-blue.svg)
![License](https://img.shields.io/badge/license-MIT-green.svg)
![Development Status](https://img.shields.io/badge/status-alpha-orange.svg)

Tsuno aims to be a drop-in replacement for Gunicorn and Uvicorn with a Rust-powered transport layer. Run your [Django](https://www.djangoproject.com/), [Flask](https://flask.palletsprojects.com/), [FastAPI](https://fastapi.tiangolo.com/), [Starlette](https://www.starlette.io/), and [connect-python](https://github.com/connectrpc/connect-python) applications with HTTP/2 support.

## Installation

```bash
pip install tsuno
```

## Quick Start

### Command Line

```bash
tsuno myapp:app --workers 4 --bind 0.0.0.0:8000
```

### Python API

**Flask (WSGI)**:
```python
from flask import Flask
from tsuno import run

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World"

if __name__ == "__main__":
    run(app)
```

**FastAPI (ASGI)**:
```python
from fastapi import FastAPI
from tsuno import run

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == "__main__":
    run(app)
```

See [`examples/`](examples/) for complete working examples.

## What Makes Tsuno Different

- **Mixed Protocol Serving**: Serve WSGI and ASGI apps simultaneously on the same server ([example](examples/mixed_wsgi_asgi.py))
- **High Performance**: Powered by Tokio and hyper
- **Complete API Compatibility**: Drop-in replacement for both Gunicorn AND Uvicorn as much as possible
- **Unix Domain Sockets**: Full UDS support for nginx integration ([example](examples/uds_example.py))

## Examples

Complete working examples in the [`examples/`](examples/) directory:

| Example | Description |
|---------|-------------|
| **[wsgi_flask_app.py](examples/wsgi_flask_app.py)** | Flask WSGI application |
| **[asgi_fastapi_app.py](examples/asgi_fastapi_app.py)** | FastAPI ASGI application |
| **[mixed_wsgi_asgi.py](examples/mixed_wsgi_asgi.py)** | **Mixed WSGI + ASGI serving** (unique to Tsuno!) |
| **[wsgi_multi_app.py](examples/wsgi_multi_app.py)** | Multiple Flask apps on different paths |
| **[asgi_multi_app.py](examples/asgi_multi_app.py)** | Multiple FastAPI apps on different paths |
| **[uds_example.py](examples/uds_example.py)** | Unix Domain Socket server |
| **[lifespan_test.py](examples/lifespan_test.py)** | ASGI Lifespan events demo |
| **[tsuno.toml](examples/tsuno.toml)** | TOML configuration example |

## Configuration

### Command Line

```bash
# Basic
tsuno myapp:app --bind 0.0.0.0:8000 --workers 4

# With auto-reload (development)
tsuno myapp:app --reload

# With Unix domain socket
tsuno myapp:app --uds /tmp/tsuno.sock

# With configuration file
tsuno myapp:app -c tsuno.toml
```

### Configuration File

**Python format** (Gunicorn-compatible):
```python
# tsuno.conf.py
bind = "0.0.0.0:8000"
workers = 4
threads = 2
log_level = "info"
```

**TOML format**:
```toml
# tsuno.toml
bind = "0.0.0.0:8000"
workers = 4
threads = 2
log_level = "info"
```

See [examples/tsuno.toml](examples/tsuno.toml) for all options.

### Python API

```python
from tsuno import run

run(
    app,
    host="0.0.0.0",
    port=8000,
    workers=4,
    reload=True,  # Development only
)
```

## Production Features

### Worker Management
- Auto-restart crashed workers
- Graceful shutdown and reload
- Worker timeout monitoring
- Max requests per worker (memory leak prevention)

### Graceful Reload (Zero-Downtime)

```bash
# Start with PID file
tsuno myapp:app --pid /var/run/tsuno.pid

# Graceful reload (no downtime)
kill -HUP $(cat /var/run/tsuno.pid)
```

### Logging
- Structured logging (text/JSON)
- Access log support
- Customizable log formats

## Performance

Performance varies by workload, platform, and configuration.
Run `wrk` or `h2load` benchmarks to measure performance on your specific hardware.

## Migration

### From Gunicorn

```bash
# Before
gunicorn myapp:app --workers 4 --bind 0.0.0.0:8000

# After (same syntax!)
tsuno myapp:app --workers 4 --bind 0.0.0.0:8000
```

### From Uvicorn

```python
# Before
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000, workers=4)

# After (compatible API!)
import tsuno
tsuno.run(app, host="0.0.0.0", port=8000, workers=4)
```

## Development Status

**Tsuno is in early development (alpha stage)**.

- ⚠️ Real-world production testing needed

**Help us test!** Report issues at [github.com/i2y/tsuno/issues](https://github.com/i2y/tsuno/issues)

## Requirements

- Python 3.11 or later
- Rust toolchain (for building from source)

## License

MIT License - see [LICENSE](LICENSE)

## Links

- **Repository**: [github.com/i2y/tsuno](https://github.com/i2y/tsuno)
- **Issues**: [github.com/i2y/tsuno/issues](https://github.com/i2y/tsuno/issues)

## Acknowledgments

Tsuno is inspired by and builds upon excellent work from:
- **Gunicorn** & **Uvicorn**: Server standards
- **Granian**: Rust-Python hybrid architecture
- **Tokio**, **hyper**, **PyO3**: Rust ecosystem


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "tsuno",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "wsgi, asgi, server, rust, async, http2, fastapi, flask, django, starlette, tsuno",
    "author": null,
    "author_email": "i2y <>",
    "download_url": "https://files.pythonhosted.org/packages/b8/fe/42ea560d3781020c60ee3ed8a898a05fefec49bb063f487eb2c1fe7a7504/tsuno-0.1.2.tar.gz",
    "platform": null,
    "description": "# \ud83e\udd84 Tsuno\n\n**High-performance WSGI/ASGI server powered by Rust**\n\n![Python Version](https://img.shields.io/badge/python-3.11+-blue.svg)\n![License](https://img.shields.io/badge/license-MIT-green.svg)\n![Development Status](https://img.shields.io/badge/status-alpha-orange.svg)\n\nTsuno aims to be a drop-in replacement for Gunicorn and Uvicorn with a Rust-powered transport layer. Run your [Django](https://www.djangoproject.com/), [Flask](https://flask.palletsprojects.com/), [FastAPI](https://fastapi.tiangolo.com/), [Starlette](https://www.starlette.io/), and [connect-python](https://github.com/connectrpc/connect-python) applications with HTTP/2 support.\n\n## Installation\n\n```bash\npip install tsuno\n```\n\n## Quick Start\n\n### Command Line\n\n```bash\ntsuno myapp:app --workers 4 --bind 0.0.0.0:8000\n```\n\n### Python API\n\n**Flask (WSGI)**:\n```python\nfrom flask import Flask\nfrom tsuno import run\n\napp = Flask(__name__)\n\n@app.route(\"/\")\ndef hello():\n    return \"Hello World\"\n\nif __name__ == \"__main__\":\n    run(app)\n```\n\n**FastAPI (ASGI)**:\n```python\nfrom fastapi import FastAPI\nfrom tsuno import run\n\napp = FastAPI()\n\n@app.get(\"/\")\nasync def root():\n    return {\"message\": \"Hello World\"}\n\nif __name__ == \"__main__\":\n    run(app)\n```\n\nSee [`examples/`](examples/) for complete working examples.\n\n## What Makes Tsuno Different\n\n- **Mixed Protocol Serving**: Serve WSGI and ASGI apps simultaneously on the same server ([example](examples/mixed_wsgi_asgi.py))\n- **High Performance**: Powered by Tokio and hyper\n- **Complete API Compatibility**: Drop-in replacement for both Gunicorn AND Uvicorn as much as possible\n- **Unix Domain Sockets**: Full UDS support for nginx integration ([example](examples/uds_example.py))\n\n## Examples\n\nComplete working examples in the [`examples/`](examples/) directory:\n\n| Example | Description |\n|---------|-------------|\n| **[wsgi_flask_app.py](examples/wsgi_flask_app.py)** | Flask WSGI application |\n| **[asgi_fastapi_app.py](examples/asgi_fastapi_app.py)** | FastAPI ASGI application |\n| **[mixed_wsgi_asgi.py](examples/mixed_wsgi_asgi.py)** | **Mixed WSGI + ASGI serving** (unique to Tsuno!) |\n| **[wsgi_multi_app.py](examples/wsgi_multi_app.py)** | Multiple Flask apps on different paths |\n| **[asgi_multi_app.py](examples/asgi_multi_app.py)** | Multiple FastAPI apps on different paths |\n| **[uds_example.py](examples/uds_example.py)** | Unix Domain Socket server |\n| **[lifespan_test.py](examples/lifespan_test.py)** | ASGI Lifespan events demo |\n| **[tsuno.toml](examples/tsuno.toml)** | TOML configuration example |\n\n## Configuration\n\n### Command Line\n\n```bash\n# Basic\ntsuno myapp:app --bind 0.0.0.0:8000 --workers 4\n\n# With auto-reload (development)\ntsuno myapp:app --reload\n\n# With Unix domain socket\ntsuno myapp:app --uds /tmp/tsuno.sock\n\n# With configuration file\ntsuno myapp:app -c tsuno.toml\n```\n\n### Configuration File\n\n**Python format** (Gunicorn-compatible):\n```python\n# tsuno.conf.py\nbind = \"0.0.0.0:8000\"\nworkers = 4\nthreads = 2\nlog_level = \"info\"\n```\n\n**TOML format**:\n```toml\n# tsuno.toml\nbind = \"0.0.0.0:8000\"\nworkers = 4\nthreads = 2\nlog_level = \"info\"\n```\n\nSee [examples/tsuno.toml](examples/tsuno.toml) for all options.\n\n### Python API\n\n```python\nfrom tsuno import run\n\nrun(\n    app,\n    host=\"0.0.0.0\",\n    port=8000,\n    workers=4,\n    reload=True,  # Development only\n)\n```\n\n## Production Features\n\n### Worker Management\n- Auto-restart crashed workers\n- Graceful shutdown and reload\n- Worker timeout monitoring\n- Max requests per worker (memory leak prevention)\n\n### Graceful Reload (Zero-Downtime)\n\n```bash\n# Start with PID file\ntsuno myapp:app --pid /var/run/tsuno.pid\n\n# Graceful reload (no downtime)\nkill -HUP $(cat /var/run/tsuno.pid)\n```\n\n### Logging\n- Structured logging (text/JSON)\n- Access log support\n- Customizable log formats\n\n## Performance\n\nPerformance varies by workload, platform, and configuration.\nRun `wrk` or `h2load` benchmarks to measure performance on your specific hardware.\n\n## Migration\n\n### From Gunicorn\n\n```bash\n# Before\ngunicorn myapp:app --workers 4 --bind 0.0.0.0:8000\n\n# After (same syntax!)\ntsuno myapp:app --workers 4 --bind 0.0.0.0:8000\n```\n\n### From Uvicorn\n\n```python\n# Before\nimport uvicorn\nuvicorn.run(app, host=\"0.0.0.0\", port=8000, workers=4)\n\n# After (compatible API!)\nimport tsuno\ntsuno.run(app, host=\"0.0.0.0\", port=8000, workers=4)\n```\n\n## Development Status\n\n**Tsuno is in early development (alpha stage)**.\n\n- \u26a0\ufe0f Real-world production testing needed\n\n**Help us test!** Report issues at [github.com/i2y/tsuno/issues](https://github.com/i2y/tsuno/issues)\n\n## Requirements\n\n- Python 3.11 or later\n- Rust toolchain (for building from source)\n\n## License\n\nMIT License - see [LICENSE](LICENSE)\n\n## Links\n\n- **Repository**: [github.com/i2y/tsuno](https://github.com/i2y/tsuno)\n- **Issues**: [github.com/i2y/tsuno/issues](https://github.com/i2y/tsuno/issues)\n\n## Acknowledgments\n\nTsuno is inspired by and builds upon excellent work from:\n- **Gunicorn** & **Uvicorn**: Server standards\n- **Granian**: Rust-Python hybrid architecture\n- **Tokio**, **hyper**, **PyO3**: Rust ecosystem\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "High-performance WSGI/ASGI server for Python, powered by Rust",
    "version": "0.1.2",
    "project_urls": {
        "Homepage": "https://github.com/i2y/tsuno",
        "Issues": "https://github.com/i2y/tsuno/issues",
        "Repository": "https://github.com/i2y/tsuno"
    },
    "split_keywords": [
        "wsgi",
        " asgi",
        " server",
        " rust",
        " async",
        " http2",
        " fastapi",
        " flask",
        " django",
        " starlette",
        " tsuno"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "dbea09f3305faa90fbd72a81162da102eccbafa9987acd27144a0a8bd294dd23",
                "md5": "78858c31c6f99b4952185d4c76b03b76",
                "sha256": "68570f8a4d6c8c7f4967b3c4dcc8a92eb5985b7397c2a3fdf1729cc4e0bf7cd9"
            },
            "downloads": -1,
            "filename": "tsuno-0.1.2-cp311-abi3-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "78858c31c6f99b4952185d4c76b03b76",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.11",
            "size": 1010424,
            "upload_time": "2025-10-21T11:35:03",
            "upload_time_iso_8601": "2025-10-21T11:35:03.659555Z",
            "url": "https://files.pythonhosted.org/packages/db/ea/09f3305faa90fbd72a81162da102eccbafa9987acd27144a0a8bd294dd23/tsuno-0.1.2-cp311-abi3-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "69a7d8e3644a79f6a48cfdfdf81c807168e712e08d0086cfb4fbb60f23a1867b",
                "md5": "ee418c87fce2da94170f94050c9d59bb",
                "sha256": "f3b35086691e7168e0ade28a658f5e12e9ea54b022d46101876fec10d8947399"
            },
            "downloads": -1,
            "filename": "tsuno-0.1.2-cp311-abi3-manylinux_2_28_aarch64.whl",
            "has_sig": false,
            "md5_digest": "ee418c87fce2da94170f94050c9d59bb",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.11",
            "size": 1082857,
            "upload_time": "2025-10-21T11:35:05",
            "upload_time_iso_8601": "2025-10-21T11:35:05.315032Z",
            "url": "https://files.pythonhosted.org/packages/69/a7/d8e3644a79f6a48cfdfdf81c807168e712e08d0086cfb4fbb60f23a1867b/tsuno-0.1.2-cp311-abi3-manylinux_2_28_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "54d0fbf3679e5a55508201eb260db017c236fbd221e52f3da0e11ec9e4ecaf6d",
                "md5": "c801ef9333c7d9306fc433290a84ef63",
                "sha256": "51378d3c454a3d7fc155b5ca033ec94971eb0bde8a1ed5f9a58af4600f31eac7"
            },
            "downloads": -1,
            "filename": "tsuno-0.1.2-cp311-abi3-manylinux_2_28_x86_64.whl",
            "has_sig": false,
            "md5_digest": "c801ef9333c7d9306fc433290a84ef63",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.11",
            "size": 1163730,
            "upload_time": "2025-10-21T11:35:06",
            "upload_time_iso_8601": "2025-10-21T11:35:06.615841Z",
            "url": "https://files.pythonhosted.org/packages/54/d0/fbf3679e5a55508201eb260db017c236fbd221e52f3da0e11ec9e4ecaf6d/tsuno-0.1.2-cp311-abi3-manylinux_2_28_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b8fe42ea560d3781020c60ee3ed8a898a05fefec49bb063f487eb2c1fe7a7504",
                "md5": "44ac9b5f190e563cee65c0edfdd67b3b",
                "sha256": "e94a7014b2bca2c466fd9815cb8d06b1ce8a9c0faa5780541b83e3092ca531ea"
            },
            "downloads": -1,
            "filename": "tsuno-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "44ac9b5f190e563cee65c0edfdd67b3b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 63451,
            "upload_time": "2025-10-21T11:35:08",
            "upload_time_iso_8601": "2025-10-21T11:35:08.564512Z",
            "url": "https://files.pythonhosted.org/packages/b8/fe/42ea560d3781020c60ee3ed8a898a05fefec49bb063f487eb2c1fe7a7504/tsuno-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-21 11:35:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "i2y",
    "github_project": "tsuno",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "tsuno"
}
        
Elapsed time: 1.90600s