Skip to content

Commit 39835c2

Browse files
committed
add extensions as runtime-checkable protocols, make BaseChannelLayer
abstract
1 parent 8244d70 commit 39835c2

File tree

1 file changed

+48
-28
lines changed

1 file changed

+48
-28
lines changed

channels/layers.py

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,18 @@
66
import re
77
import string
88
import time
9+
from abc import ABC, abstractmethod
910
from copy import deepcopy
10-
from typing import Dict, Iterable, List, Optional, Tuple
11+
from typing import (
12+
Dict,
13+
Iterable,
14+
List,
15+
NoReturn,
16+
Optional,
17+
Protocol,
18+
Tuple,
19+
runtime_checkable,
20+
)
1121

1222
from django.conf import settings
1323
from django.core.signals import setting_changed
@@ -97,7 +107,39 @@ def set(self, key: str, layer: BaseChannelLayer):
97107
return old
98108

99109

100-
class BaseChannelLayer:
110+
@runtime_checkable
111+
class WithFlushExtension(Protocol):
112+
async def flush(self) -> NoReturn:
113+
"""
114+
Clears messages and if available groups
115+
"""
116+
117+
async def close(self) -> NoReturn:
118+
"""
119+
Close connection to the layer. Called before stopping layer.
120+
Unusable after.
121+
"""
122+
123+
124+
@runtime_checkable
125+
class WithGroupsExtension(Protocol):
126+
async def group_add(self, group: str, channel: str):
127+
"""
128+
Adds the channel name to a group.
129+
"""
130+
131+
async def group_discard(self, group: str, channel: str) -> NoReturn:
132+
"""
133+
Removes the channel name from a group when it exists.
134+
"""
135+
136+
async def group_send(self, group: str, message: dict) -> NoReturn:
137+
"""
138+
Sends message to group
139+
"""
140+
141+
142+
class BaseChannelLayer(ABC):
101143
"""
102144
Base channel layer class that others can inherit from, with useful
103145
common functionality.
@@ -199,51 +241,29 @@ def non_local_name(self, name: str) -> str:
199241
else:
200242
return name
201243

244+
@abstractmethod
202245
async def send(self, channel: str, message: dict):
203246
"""
204247
Send a message onto a (general or specific) channel.
205248
"""
206-
raise NotImplementedError()
207249

250+
@abstractmethod
208251
async def receive(self, channel: str) -> dict:
209252
"""
210253
Receive the first message that arrives on the channel.
211254
If more than one coroutine waits on the same channel, a random one
212255
of the waiting coroutines will get the result.
213256
"""
214-
raise NotImplementedError()
215257

258+
@abstractmethod
216259
async def new_channel(self, prefix: str = "specific.") -> str:
217260
"""
218261
Returns a new channel name that can be used by something in our
219262
process as a specific channel.
220263
"""
221-
raise NotImplementedError()
222-
223-
# Flush extension
224-
225-
async def flush(self):
226-
raise NotImplementedError()
227-
228-
async def close(self):
229-
raise NotImplementedError()
230-
231-
# Groups extension
232-
233-
async def group_add(self, group: str, channel: str):
234-
"""
235-
Adds the channel name to a group.
236-
"""
237-
raise NotImplementedError()
238-
239-
async def group_discard(self, group: str, channel: str):
240-
raise NotImplementedError()
241-
242-
async def group_send(self, group: str, message: dict):
243-
raise NotImplementedError()
244264

245265

246-
class InMemoryChannelLayer(BaseChannelLayer):
266+
class InMemoryChannelLayer(WithFlushExtension, WithGroupsExtension, BaseChannelLayer):
247267
"""
248268
In-memory channel layer implementation
249269
"""

0 commit comments

Comments
 (0)