add a stateful encoder (irctokens.StatefulEncoder())

This commit is contained in:
jesopo 2020-03-11 15:17:17 +00:00
parent 3cdc163b87
commit 49d2e78475
4 changed files with 48 additions and 4 deletions

View File

@ -31,17 +31,30 @@ if line.command == "PRIVMSG":
```
### stateful
below is an example of a fully socket-wise safe IRC client connection that will
connect and join a channel. both protocol sending and receiving are handled by
irctokens.
```python
import irctokens, socket
NICK = "nickname"
CHAN = "#channel"
d = irctokens.StatefulDecoder()
e = irctokens.StatefulEncoder()
s = socket.socket()
s.connect(("127.0.0.1", 6667))
def _send(line):
s.send(f"{line}\r\n".encode("utf8"))
print(f"> {line.format()}")
e.push(line)
while e.pending():
e.pop(s.send(e.pending()))
_send(irctokens.format("USER", ["username", "0", "*", "real name"]))
_send(irctokens.format("USER", [NICK, "0", "*", "real name"]))
_send(irctokens.format("NICK", ["nickname"]))
while True:
@ -51,11 +64,12 @@ while True:
break
for line in lines:
print(f"< {line.format()}")
if line.command == "PING":
to_send = irctokens.format("PONG", [line.params[0]])
_send(to_send)
elif line.command == "001":
to_send = irctokens.format("JOIN", ["#test"])
to_send = irctokens.format("JOIN", [CHAN])
_send(to_send)
```

View File

@ -1,2 +1,2 @@
from .protocol import Line, tokenise, format
from .stateful import StatefulDecoder
from .stateful import StatefulDecoder, StatefulEncoder

View File

@ -21,3 +21,16 @@ class StatefulDecoder(object):
except UnicodeDecodeError as e:
decode_lines.append(line.decode(self._fallback))
return [tokenise(l) for l in decode_lines]
class StatefulEncoder(object):
def __init__(self):
self._buffer = b""
def pending(self) -> bytes:
return self._buffer
def push(self, line: Line) -> bytes:
self._buffer += f"{line.format()}\r\n".encode("utf8")
return self._buffer
def pop(self, byte_count: int):
self._buffer = self._buffer[byte_count:]

17
test/stateful_encode.py Normal file
View File

@ -0,0 +1,17 @@
import unittest
import irctokens
class TestPush(unittest.TestCase):
def test(self):
e = irctokens.StatefulEncoder()
line = irctokens.tokenise("PRIVMSG #channel hello")
e.push(line)
self.assertEqual(e.pending(), b"PRIVMSG #channel hello\r\n")
class TestPop(unittest.TestCase):
def test(self):
e = irctokens.StatefulEncoder()
line = irctokens.tokenise("PRIVMSG #channel hello")
e.push(line)
e.pop(len(b"PRIVMSG #channel hello"))
self.assertEqual(e.pending(), b"\r\n")