support labeled-response (but don't REQ it yet)

This commit is contained in:
jesopo 2020-04-13 18:23:05 +01:00
parent bd424d11ff
commit 8656f63d09
4 changed files with 43 additions and 12 deletions

View file

@ -33,10 +33,15 @@ class SendPriority(IntEnum):
DEFAULT = MEDIUM DEFAULT = MEDIUM
class SentLine(object): class SentLine(object):
def __init__(self, priority: int, line: Line): def __init__(self,
id: int,
priority: int,
line: Line):
self.id = id
self.priority = priority self.priority = priority
self.line = line self.line = line
self.future: Future = Future() self.future: Future = Future()
def __lt__(self, other: "SentLine") -> bool: def __lt__(self, other: "SentLine") -> bool:
return self.priority < other.priority return self.priority < other.priority
@ -61,9 +66,11 @@ class IServer(Server):
params: ConnectionParams params: ConnectionParams
desired_caps: Set[ICapability] desired_caps: Set[ICapability]
def send_raw(self, line: str, priority=SendPriority.DEFAULT) -> Future: def send_raw(self, line: str, priority=SendPriority.DEFAULT
) -> Awaitable[SentLine]:
pass pass
def send(self, line: Line, priority=SendPriority.DEFAULT) -> Future: def send(self, line: Line, priority=SendPriority.DEFAULT
) -> Awaitable[SentLine]:
pass pass
def wait_for(self, response: IMatchResponse) -> Awaitable[Line]: def wait_for(self, response: IMatchResponse) -> Awaitable[Line]:

View file

@ -34,7 +34,15 @@ class Capability(ICapability):
alias=self.alias, alias=self.alias,
depends_on=self.depends_on[:]) depends_on=self.depends_on[:])
CAP_SASL = Capability("sasl") CAP_SASL = Capability("sasl")
CAP_ECHO = Capability("echo-message")
CAP_LABEL = Capability("labeled-response", "draft/labeled-response-0.2")
LABEL_TAG = {
"draft/labeled-response-0.2": "draft/label",
"labeled-response": "label"
}
CAPS: List[ICapability] = [ CAPS: List[ICapability] = [
Capability("multi-prefix"), Capability("multi-prefix"),
Capability("chghost"), Capability("chghost"),

View file

@ -6,7 +6,7 @@ from asyncio_throttle import Throttler
from ircstates import Emit, Channel, NUMERIC_NAMES from ircstates import Emit, Channel, NUMERIC_NAMES
from irctokens import build, Line, tokenise from irctokens import build, Line, tokenise
from .ircv3 import CAPContext, CAP_SASL from .ircv3 import CAPContext, CAP_ECHO, CAP_SASL, CAP_LABEL, LABEL_TAG
from .sasl import SASLContext, SASLResult from .sasl import SASLContext, SASLResult
from .matching import ResponseOr, Numerics, Numeric, ParamAny, ParamFolded from .matching import ResponseOr, Numerics, Numeric, ParamAny, ParamFolded
from .asyncs import MaybeAwait from .asyncs import MaybeAwait
@ -33,6 +33,7 @@ class Server(IServer):
self.sasl_state = SASLResult.NONE self.sasl_state = SASLResult.NONE
self._sent_count: int = 0
self._wait_for: List[Tuple["Future[Line]", IMatchResponse]] = [] self._wait_for: List[Tuple["Future[Line]", IMatchResponse]] = []
self._write_queue: PriorityQueue[SentLine] = PriorityQueue() self._write_queue: PriorityQueue[SentLine] = PriorityQueue()
self.desired_caps: Set[ICapability] = set([]) self.desired_caps: Set[ICapability] = set([])
@ -48,12 +49,27 @@ class Server(IServer):
return hostmask return hostmask
def send_raw(self, line: str, priority=SendPriority.DEFAULT def send_raw(self, line: str, priority=SendPriority.DEFAULT
) -> Future: ) -> Awaitable[SentLine]:
return self.send(tokenise(line), priority) return self.send(tokenise(line), priority)
def send(self, line: Line, priority=SendPriority.DEFAULT) -> Future: def send(self, line: Line, priority=SendPriority.DEFAULT
prio_line = SentLine(priority, line) ) -> Awaitable[SentLine]:
self._write_queue.put_nowait(prio_line) sent_line = SentLine(self._sent_count, priority, line)
return prio_line.future self._sent_count += 1
label = self.cap_available(CAP_LABEL)
if not label is None:
tag = LABEL_TAG[label]
if line.tags is None or not tag in line.tags:
if line.tags is None:
line.tags = {}
line.tags[tag] = str(sent_line.id)
self._write_queue.put_nowait(sent_line)
async def _assure() -> SentLine:
await sent_line.future
return sent_line
return MaybeAwait(_assure)
def set_throttle(self, rate: int, time: float): def set_throttle(self, rate: int, time: float):
self.throttle.rate_limit = rate self.throttle.rate_limit = rate
@ -164,7 +180,7 @@ class Server(IServer):
await self._writer.drain() await self._writer.drain()
for line in lines: for line in lines:
line.future.set_result(None) line.future.set_result(line)
await self.line_send(line.line) await self.line_send(line.line)
return [l.line for l in lines] return [l.line for l in lines]

View file

@ -1,5 +1,5 @@
anyio ==1.3.0 anyio ==1.3.0
asyncio-throttle ==1.0.1 asyncio-throttle ==1.0.1
dataclasses ==0.6 dataclasses ==0.6
ircstates ==0.8.8 ircstates ==0.8.9
async_stagger ==0.3.0 async_stagger ==0.3.0