Skip to content

Commit

Permalink
Added tests to setup and added the offlineirc for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
howroyd committed Aug 26, 2023
1 parent 83a9380 commit 7201214
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
omit = run_tests.py, __init__.py
18 changes: 16 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[build-system]
requires = ["setuptools>=61.0"]
requires = ["pytest", "pytest-cov", "setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "twitchirc_drgreengiant"
version = "2.0.0rc0"
version = "2.0.0"
authors = [{ name = "Simon Howroyd", email = "[email protected]" }]
description = "A simple receive only Twitch IRC client"
keywords = ["twitch", "irc", "chat"]
Expand All @@ -21,3 +21,17 @@ classifiers = [
"Homepage" = "https://github.com/howroyd/twitchirc"
"Repository" = "https://github.com/howroyd/twitchirc"
"Bug Tracker" = "https://github.com/howroyd/twitchirc/issues"

[tool.setuptools.packages.find]
where = ["src", "tests"]

[tool.pytest.ini_options]
minversion = "2.0"
python_files = ["tests/test_*.py", "tests/*_test.py"]
addopts = [
"--cov=.",
"--cov-report=html",
"--cov-report=term-missing",
"--cov-fail-under=95",
]
filterwarnings = "ignore::DeprecationWarning"
82 changes: 82 additions & 0 deletions src/twitchirc_drgreengiant/offlineirc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!./.venv/bin/python3
import dataclasses
import multiprocessing as mp
import queue
import sys
from typing import NoReturn, Self

from . import twitchirc


@dataclasses.dataclass(slots=True)
class OfflineIrcThreadArgs:
"""Arguments to pass to the offline IRC thread"""
username: str
channel: frozenset[str]
queue: mp.Queue = dataclasses.field(default_factory=mp.Queue)


def _offline_irc_thread(args: OfflineIrcThreadArgs) -> NoReturn:
"""Thread for offline IRC connection
Rather than reading from the IRC server, we read from stdin
"""
sys.stdin = open(0)

while True:
userinput = sys.stdin.readline().strip()

msg = twitchirc.TwitchMessage(
twitchirc.TwitchMessageEnum.PRIVMSG,
args.username,
next(iter(args.channel)),
userinput
)

args.queue.put(msg)


class OfflineIrc:
"""Context manager for offline IRC connection which reads from stdin rather than the IRC server"""

def __init__(self, channel: frozenset[str], username: str | None = None):
if not channel or channel.issubset(frozenset([""])):
raise twitchirc.TwitchIrcConnectionError("No channels specified")
self._processdata = OfflineIrcThreadArgs(
username=username or "justinfan97339",
channel=channel
)
self._process: mp.Process | None = None

@property
def queue(self) -> mp.Queue:
"""Returns the queue of messages from stdin"""
return self._processdata.queue

@staticmethod
def get_message(irc: Self, *, timeout: float = 0.1) -> twitchirc.TwitchMessage | None:
"""Returns a message from stdin, or None if no message is available"""
msg: twitchirc.TwitchMessage | None = None
try:
msg = irc.queue.get(timeout=timeout)
if not msg:
raise twitchirc.NoMessageException
except (twitchirc.NoMessageException, queue.Empty):
pass
return msg

def start(self) -> None:
"""Starts the connection to pretend IRC server"""
self._process = mp.Process(target=_offline_irc_thread, args=(self._processdata,))
self._process.start()

def stop(self) -> None:
"""Forcibly terminate the connection. May deadlock anyone waiting on the queue"""
# FIXME - This is a bit of a hack. We should probably send a message to the thread to tell it to stop
self._process.terminate() if self._process else None

def __enter__(self):
self.start()
return self

def __exit__(self, exc_type, exc_value, traceback):
self.stop()
2 changes: 1 addition & 1 deletion src/twitchirc_drgreengiant/twitchirc.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def get_message(irc: Self, *, timeout: float = 0.1) -> TwitchMessage | None:

if __name__ == "__main__":
testchannels = frozenset([""])
#testchannels = frozenset(["drgreengiant"])
# testchannels = frozenset(["drgreengiant"])

with TwitchIrc(testchannels) as irc:
while True:
Expand Down

0 comments on commit 7201214

Please sign in to comment.