Skip to content

Commit f6f330b

Browse files
committed
Django channels stubs
1 parent 30b7b67 commit f6f330b

27 files changed

+615
-0
lines changed

pyrightconfig.stricter.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"stubs/braintree",
3333
"stubs/caldav",
3434
"stubs/cffi",
35+
"stubs/channels",
3536
"stubs/click-web",
3637
"stubs/corus",
3738
"stubs/dateparser",

stubs/channels/METADATA.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version = "4.*"
2+
upstream_repository = "https://github.com/django/channels"
3+
requires = ["django-stubs", "asgiref"]
4+
requires_python = ">=3.10"
5+
6+
[tool.stubtest]
7+
skip = true # due to the need of django mypy plugin config, it should be skipped.
8+
stubtest_requirements = ["daphne"]

stubs/channels/channels/__init__.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__version__: str
2+
DEFAULT_CHANNEL_LAYER: str

stubs/channels/channels/apps.pyi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
from django.utils.functional import _StrOrPromise
3+
4+
class ChannelsConfig(AppConfig):
5+
name: str = ...
6+
verbose_name: _StrOrPromise = ...

stubs/channels/channels/auth.pyi

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import Any
2+
3+
from asgiref.typing import ASGIReceiveCallable, ASGISendCallable
4+
from channels.middleware import BaseMiddleware
5+
from django.contrib.auth.backends import BaseBackend
6+
from django.contrib.auth.base_user import AbstractBaseUser
7+
from django.contrib.auth.models import AnonymousUser
8+
from django.utils.functional import LazyObject
9+
10+
from .consumer import _ChannelScope, _LazySession
11+
from .db import database_sync_to_async
12+
from .utils import _ChannelApplication
13+
14+
@database_sync_to_async
15+
def get_user(scope: _ChannelScope) -> AbstractBaseUser | AnonymousUser: ...
16+
@database_sync_to_async
17+
def login(scope: _ChannelScope, user: AbstractBaseUser, backend: BaseBackend | None = ...) -> None: ...
18+
@database_sync_to_async
19+
def logout(scope: _ChannelScope) -> None: ...
20+
def _get_user_session_key(session: _LazySession) -> Any: ...
21+
22+
class UserLazyObject(AbstractBaseUser, LazyObject):
23+
def _setup(self) -> None: ...
24+
25+
class AuthMiddleware(BaseMiddleware):
26+
def populate_scope(self, scope: _ChannelScope) -> None: ...
27+
async def resolve_scope(self, scope: _ChannelScope) -> None: ...
28+
async def __call__(
29+
self, scope: _ChannelScope, receive: ASGIReceiveCallable, send: ASGISendCallable
30+
) -> _ChannelApplication: ...
31+
32+
def AuthMiddlewareStack(inner: _ChannelApplication) -> _ChannelApplication: ...

stubs/channels/channels/consumer.pyi

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from collections.abc import Awaitable
2+
from typing import Any, ClassVar, Protocol
3+
4+
from asgiref.typing import ASGIReceiveCallable, ASGISendCallable, Scope, WebSocketScope
5+
from channels.auth import UserLazyObject
6+
from channels.db import database_sync_to_async
7+
from django.contrib.sessions.backends.base import SessionBase
8+
from django.utils.functional import LazyObject
9+
10+
class _LazySession(SessionBase, LazyObject): # type: ignore[misc]
11+
_wrapped: SessionBase
12+
13+
# Base ASGI Scope definition
14+
class _ChannelScope(WebSocketScope, total=False):
15+
# Channel specific
16+
channel: str
17+
url_route: dict[str, Any]
18+
path_remaining: str
19+
20+
# Auth specific
21+
cookies: dict[str, str]
22+
session: _LazySession
23+
user: UserLazyObject | None
24+
25+
def get_handler_name(message: dict[str, Any]) -> str: ...
26+
27+
class _ASGIApplicationProtocol(Protocol):
28+
consumer_class: Any
29+
consumer_initkwargs: dict[str, Any]
30+
31+
def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable) -> Awaitable[None]: ...
32+
33+
class AsyncConsumer:
34+
_sync: ClassVar[bool] = ...
35+
channel_layer_alias: ClassVar[str] = ...
36+
37+
scope: _ChannelScope
38+
channel_layer: Any
39+
channel_name: str
40+
channel_receive: ASGIReceiveCallable
41+
base_send: ASGISendCallable
42+
43+
async def __call__(self, scope: _ChannelScope, receive: ASGIReceiveCallable, send: ASGISendCallable) -> None: ...
44+
async def dispatch(self, message: dict[str, Any]) -> None: ...
45+
async def send(self, message: dict[str, Any]) -> None: ...
46+
@classmethod
47+
def as_asgi(cls, **initkwargs: Any) -> _ASGIApplicationProtocol: ...
48+
49+
class SyncConsumer(AsyncConsumer):
50+
_sync: ClassVar[bool] = ...
51+
52+
@database_sync_to_async
53+
def dispatch(self, message: dict[str, Any]) -> None: ... # type: ignore[override]
54+
def send(self, message: dict[str, Any]) -> None: ... # type: ignore[override]

stubs/channels/channels/db.pyi

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from asyncio import BaseEventLoop
2+
from collections.abc import Callable, Coroutine
3+
from typing import Any, TypeVar
4+
from typing_extensions import ParamSpec
5+
6+
from asgiref.sync import SyncToAsync
7+
8+
_P = ParamSpec("_P")
9+
_R = TypeVar("_R")
10+
11+
class DatabaseSyncToAsync(SyncToAsync[_P, _R]):
12+
def thread_handler(self, loop: BaseEventLoop, *args: Any, **kwargs: Any) -> Any: ...
13+
14+
def database_sync_to_async(func: Callable[_P, _R]) -> Callable[_P, Coroutine[Any, Any, _R]]: ...
15+
async def aclose_old_connections() -> None: ...
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class RequestAborted(Exception): ...
2+
class RequestTimeout(RequestAborted): ...
3+
class InvalidChannelLayerError(ValueError): ...
4+
class AcceptConnection(Exception): ...
5+
class DenyConnection(Exception): ...
6+
class ChannelFull(Exception): ...
7+
class MessageTooLarge(Exception): ...
8+
class StopConsumer(Exception): ...

stubs/channels/channels/generic/__init__.pyi

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from collections.abc import Iterable
2+
from typing import Any
3+
4+
from asgiref.typing import HTTPDisconnectEvent, HTTPRequestEvent, HTTPScope
5+
from channels.consumer import AsyncConsumer
6+
7+
class AsyncHttpConsumer(AsyncConsumer):
8+
body: list[bytes]
9+
scope: HTTPScope # type: ignore[assignment]
10+
11+
def __init__(self, *args: Any, **kwargs: Any) -> None: ...
12+
async def send_headers(self, *, status: int = ..., headers: Iterable[tuple[bytes, bytes]] | None = ...) -> None: ...
13+
async def send_body(self, body: bytes, *, more_body: bool = ...) -> None: ...
14+
async def send_response(self, status: int, body: bytes, **kwargs: Any) -> None: ...
15+
async def handle(self, body: bytes) -> None: ...
16+
async def disconnect(self) -> None: ...
17+
async def http_request(self, message: HTTPRequestEvent) -> None: ...
18+
async def http_disconnect(self, message: HTTPDisconnectEvent) -> None: ...
19+
async def send(self, message: dict[str, Any]) -> None: ... # type: ignore[override]

0 commit comments

Comments
 (0)