Skip to main content
rule

tornado — Cursor rule: async/await in Tornado apps

A Cursor rule that pins down Tornado code style: async/await for every I/O call, full type hints, and one shared error handler.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/tornado.mdc
Open on GitHub

What tornado does

The .cursor/rules/tornado.mdc file plugs into Cursor and applies to **/*.py. Inside is a set of Tornado conventions for Python 3.9+ with bad/good code samples. The agent reads them while editing and keeps new code in that shape.

The core demand is no blocking I/O in handlers. time.sleep stalls the IOLoop, so the rule swaps it for await asyncio.sleep. Same story with the older callback APIs: Tornado runs on top of asyncio, so any network or disk call should be async def with await. Second point is typing — from __future__ import annotations plus annotations on request arguments.

Errors get handled in one place. Tornado already deals with malformed headers and broken multipart-form-data, and the rule forbids catching those exceptions inside every handler. Instead it suggests a base class that returns a consistent response for HTTPError. If your project already has its own error layer, expect to rewrite the rule to match, otherwise the agent will keep pulling code toward the suggested scheme.

What it helps with

  • strip blocking calls out of Tornado handlers
  • move legacy code from callback APIs to async/await
  • add type hints to handlers and request arguments
  • route error responses through one base class
  • stop catching malformed header and multipart exceptions by hand

Example prompts for the agent

  • check this handler for blocking I/O and rewrite it with async/await
  • add type hints to this RequestHandler following the tornado rule
  • give me a BaseHandler with a shared HTTPError response instead of try/except in every method

How to install tornado

Manually: put the files in place

.cursor/rules/tornado.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about tornado

How do I install the tornado rule in Cursor?

Create .cursor/rules/tornado.mdc in your project root and paste the rule contents into it.

What does the tornado rule do?

It tells Cursor how to write Tornado code: async/await instead of blocking calls, full type annotations, and centralized error handling.

Which files does the rule cover?

It declares the glob **/*.py, so every Python file in the project.

Source text

tornado.mdc · CC0-1.0
---
description: Definitive guidelines for writing high-performance, secure, and maintainable Tornado applications using modern Python 3.9+ async/await patterns and best practices.
globs: **/*.py
---
# tornado Best Practices

Tornado is a powerful, non-blocking web framework ideal for high-concurrency applications, WebSockets, and long-polling. These rules enforce modern (Python 3.9+, 2025 standards) best practices, ensuring your code is performant, secure, and maintainable.

## 1. Embrace `async/await` for All I/O

Always use `async def` and `await` for any I/O-bound operations. Avoid older callback-based APIs. Tornado integrates seamlessly with `asyncio`.

❌ BAD: Blocking I/O in a handler
```python
import time
import tornado.web

class BadHandler(tornado.web.RequestHandler):
    def get(self) -> None:
        time.sleep(1) # Blocks the IOLoop
        self.write("Hello, blocked world!")
```

✅ GOOD: Asynchronous I/O
```python
import asyncio
import tornado.web

class GoodHandler(tornado.web.RequestHandler):
    async def get(self) -> None:
        await asyncio.sleep(1) # Non-blocking
        self.write("Hello, async world!")
```

## 2. Leverage Type Hints

Utilize full type annotations (`from __future__ import annotations`) for clarity, static analysis, and improved IDE support. Tornado's stubs are well-maintained.

❌ BAD: Untyped handler
```python
class UntypedHandler(tornado.web.RequestHandler):
    def post(self):
        name = self.get_argument("name")
        self.write(f"Hello, {name}")
```

✅ GOOD: Fully typed handler
```python
from __future__ import annotations
import tornado.web

class TypedHandler(tornado.web.RequestHandler):
    async def post(self) -> None:
        name: str = self.get_argument("name")
        self.write(f"Hello, {name}")
```

## 3. Centralized Error Handling

Let Tornado's built-in error handling for malformed requests (e.g., `multipart-form-data`, invalid headers) propagate. Implement a custom `ErrorHandler` for consistent responses.

❌ BAD: Ignoring or manually handling low-level header errors
```python
# This is an anti-pattern; Tornado handles these automatically.
# Do not try to catch exceptions for malformed headers or multipart data
# directly in every handler. Let it propagate.
```

✅ GOOD: Custom `HTTPError` handler
```python
from __future__ import annotations
import tornado.web
import json

class BaseHandler(tornado.web.RequestHandler):

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Similar IDE rules

All IDE rules for Backend and APIs →

From the same set69

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor