Skip to main content

The missing toolkit for Channels — auth, logging, consumers, and more.

Project description

PyPI Code Coverage Test Checked with mypy Checked with pyright Interrogate Badge

The missing toolkit for WebSocket development — supporting Django Channels, FastAPI, and any ASGI-compatible framework with decorator-based handlers, automatic AsyncAPI documentation generation, authentication, logging, and structured messaging.

Installation

Basic Installation (Core Only)

pip install chanx

For Django Channels Projects

pip install "chanx[channels]"

For FastAPI and Other ASGI Frameworks

pip install "chanx[fast_channels]"

For complete documentation, visit chanx docs.

Introduction

Building real-time WebSocket applications shouldn’t require reinventing the wheel for each framework. Chanx brings consistency, type safety, and powerful tooling to WebSocket development across Django Channels, FastAPI, and any ASGI-compatible framework.

With Chanx, you get decorator-based message handlers that automatically generate type-safe routing, Pydantic validation, and AsyncAPI 3.0 documentation. Whether you’re building a chat system, live notifications, or real-time collaboration features, Chanx provides the missing pieces that make WebSocket development as straightforward as building REST APIs.

Quick Look

See how Chanx works with decorator-based handlers. Define your WebSocket consumer with @ws_handler for client messages and @event_handler for server-side events:

from typing import Literal
from pydantic import BaseModel
from chanx.core.decorators import ws_handler, event_handler, channel
from chanx.core.websocket import AsyncJsonWebsocketConsumer
from chanx.messages.incoming import PingMessage
from chanx.messages.outgoing import PongMessage
from chanx.messages.base import BaseMessage

# Define your message types
class ChatPayload(BaseModel):
    message: str

class ChatMessage(BaseMessage):
    action: Literal["chat"] = "chat"
    payload: ChatPayload

class ChatNotificationMessage(BaseMessage):
    action: Literal["chat_notification"] = "chat_notification"
    payload: ChatPayload

class NotificationPayload(BaseModel):
    alert: str

class NotificationEvent(BaseMessage):
    action: Literal["notification_event"] = "notification_event"
    payload: NotificationPayload

class NotificationMessage(BaseMessage):
    action: Literal["notification"] = "notification"
    payload: NotificationPayload

@channel(name="chat", description="Real-time chat API")
class ChatConsumer(AsyncJsonWebsocketConsumer):
    @ws_handler(summary="Handle ping requests")
    async def handle_ping(self, message: PingMessage) -> PongMessage:
        return PongMessage()

    @ws_handler(
        summary="Handle chat messages",
        output_type=ChatNotificationMessage,
    )
    async def handle_chat(self, message: ChatMessage) -> None:
        # Broadcast to all clients in group
        await self.broadcast_message(
            ChatNotificationMessage(
                payload=ChatPayload(message=f"User: {message.payload.message}")
            )
        )

    @event_handler(output_type=NotificationMessage)
    async def handle_notification(self, event: NotificationEvent) -> NotificationMessage:
        """Handle notifications from background workers."""
        return NotificationMessage(payload=event.payload)

Client Usage:

// Send a ping - client receives immediate response
websocket.send(JSON.stringify({"action": "ping"}))
// Receives: {"action": "pong", "payload": null}

// Send a chat message - all clients in group receive broadcast
websocket.send(JSON.stringify({
    "action": "chat",
    "payload": {"message": "Hello everyone!"}
}))
// All clients receive: {"action": "chat_notification", "payload": {"message": "User: Hello everyone!"}}

Send events from anywhere in your application:

# From Django views, Celery tasks, management scripts, etc.
ChatConsumer.broadcast_event_sync(
    NotificationEvent(payload={"alert": "Server maintenance starting"}),
    groups=["chat_room"]
)
# All WebSocket clients receive: {"action": "notification", "payload": {"alert": "..."}}

The framework automatically discovers your handlers, validates messages with Pydantic, and generates AsyncAPI documentation.

Key Features & Components

  • Multi-Framework Support: Works with Django Channels, FastAPI, and any ASGI-compatible framework via chanx.ext.channels and chanx.ext.fast_channels

  • Decorator-Based Architecture: Use @ws_handler, @event_handler, and @channel decorators with automatic message routing and validation

  • AsyncAPI Documentation: Generate AsyncAPI 3.0 specifications automatically from decorated handlers and message types

  • Type-Safe Messaging: Pydantic-based validation with automatic discriminated unions and full mypy/pyright support

  • Authentication System: DRF integration for Django, flexible authenticator base classes for other frameworks

  • Channel Layer Integration: Type-safe pub/sub messaging, group broadcasting, and event handling across your application

  • Comprehensive Testing: Framework-specific test utilities for WebSocket consumers and group messaging

  • Production Features: Structured logging, error handling, and battle-tested patterns for scalable applications

Type Parameters and AsyncAPI Generation

The framework automatically generates AsyncAPI 3.0 specifications from your decorated handlers. You can specify event types for type safety:

@channel(name="chat", description="Real-time chat system", tags=["chat"])
class ChatConsumer(AsyncJsonWebsocketConsumer[NotificationEvent]):
    @ws_handler(
        summary="Handle chat messages",
        description="Process chat messages and broadcast to room",
        output_type=ChatNotificationMessage,
    )
    async def handle_chat(self, message: ChatMessage) -> None:
        await self.broadcast_message(
            ChatNotificationMessage(
                payload=ChatPayload(message=f"💬 {message.payload.message}")
            ),
        )

    @event_handler
    async def handle_notification(self, event: NotificationEvent) -> NotificationMessage:
        return NotificationMessage(payload=event.payload)

Sending Events and Broadcasting

Send events to specific consumers or broadcast to groups:

# Send event to specific channel
await MyConsumer.send_event(
    NotificationEvent(payload="Hello!"),
    channel_name="specific.channel.name"
)

# Broadcast event to group
await MyConsumer.broadcast_event(
    SystemNotify(payload="Server maintenance in 5 minutes"),
    groups=["admin_users"]
)

Configuration

Django Configuration

For Django projects, configure Chanx through the CHANX dictionary in your Django settings:

# settings.py
CHANX = {
    # Message configuration
    'MESSAGE_ACTION_KEY': 'action',  # Key name for action field in messages
    'CAMELIZE': False,  # Whether to camelize/decamelize messages for JavaScript clients

    # Completion messages
    'SEND_COMPLETION': False,  # Whether to send completion message after processing messages

    # Messaging behavior
    'SEND_MESSAGE_IMMEDIATELY': True,  # Whether to yield control after sending messages
    'LOG_WEBSOCKET_MESSAGE': True,  # Whether to log WebSocket messages
    'LOG_IGNORED_ACTIONS': [],  # Message actions that should not be logged
}

Other Frameworks Configuration

For FastAPI and other ASGI frameworks, configure Chanx by subclassing AsyncJsonWebsocketConsumer and setting class attributes:

from chanx.core.websocket import AsyncJsonWebsocketConsumer

class BaseConsumer(AsyncJsonWebsocketConsumer):
    # Message configuration
    camelize = False  # Whether to camelize/decamelize messages
    send_completion = False  # Whether to send completion messages
    send_message_immediately = True  # Whether to yield control after sending
    log_websocket_message = True  # Whether to log WebSocket messages
    log_ignored_actions = []  # Message actions to ignore in logs

    # Channel layer configuration
    channel_layer_alias = "default"  # Channel layer alias to use

You can also configure per-consumer by setting attributes directly:

@channel(name="chat")
class ChatConsumer(BaseConsumer):
    send_completion = True  # Override base setting
    log_ignored_actions = ["ping", "pong"]  # Don't log ping/pong messages

Learn More

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chanx-1.1.1.tar.gz (51.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chanx-1.1.1-py3-none-any.whl (69.2 kB view details)

Uploaded Python 3

File details

Details for the file chanx-1.1.1.tar.gz.

File metadata

  • Download URL: chanx-1.1.1.tar.gz
  • Upload date:
  • Size: 51.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for chanx-1.1.1.tar.gz
Algorithm Hash digest
SHA256 5c2607051951635dc16e0468b8165d9b0a3c75e6dac79a2d2697d5611a53c200
MD5 f00210b212070562ca4fcd45fbfd2417
BLAKE2b-256 d544f65e86e906b3b57b65d1cf954182abcb6b3dd3a64f7f7a186e7ba16c10f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for chanx-1.1.1.tar.gz:

Publisher: publish.yml on huynguyengl99/chanx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chanx-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: chanx-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 69.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for chanx-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c43905434b8e5131406777232d666a12bcac6b79c3819ece9840d9f9ca20474d
MD5 15707a9537fbbcd32ffee56a83574ea9
BLAKE2b-256 1918ef24036cc495364199f332331a9ad9562705444fea7786c615ea05033ffd

See more details on using hashes here.

Provenance

The following attestation bundles were made for chanx-1.1.1-py3-none-any.whl:

Publisher: publish.yml on huynguyengl99/chanx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page