Skip to content

Commit ccc7ad3

Browse files
committed
Harden IrcConnection.close() against broken transports
1 parent 3d5e491 commit ccc7ad3

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

irc_connection.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import contextlib
23
import logging
34
import traceback
45

@@ -91,4 +92,5 @@ async def close(self):
9192
self.ready = False
9293
if self.writer:
9394
self.writer.close()
94-
await self.writer.wait_closed()
95+
with contextlib.suppress(OSError):
96+
await self.writer.wait_closed()

tests/test_irc_connection.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from unittest.mock import MagicMock
1+
from unittest.mock import AsyncMock, MagicMock
22

33
from irc_connection import IrcConnection
44

@@ -76,3 +76,36 @@ async def fake_read(n):
7676

7777
assert lines == []
7878
assert conn.ready is False
79+
80+
81+
class TestClose:
82+
async def test_close_suppresses_oserror_from_wait_closed(self):
83+
conn = IrcConnection()
84+
conn.writer = MagicMock()
85+
conn.writer.close = MagicMock()
86+
conn.writer.wait_closed = AsyncMock(side_effect=ConnectionResetError("Connection reset by peer"))
87+
88+
await conn.close() # Should not raise
89+
90+
assert conn.ready is False
91+
conn.writer.close.assert_called_once()
92+
93+
async def test_close_works_normally(self):
94+
conn = IrcConnection()
95+
conn.writer = MagicMock()
96+
conn.writer.close = MagicMock()
97+
conn.writer.wait_closed = AsyncMock()
98+
99+
await conn.close()
100+
101+
assert conn.ready is False
102+
conn.writer.close.assert_called_once()
103+
conn.writer.wait_closed.assert_awaited_once()
104+
105+
async def test_close_no_writer(self):
106+
conn = IrcConnection()
107+
conn.writer = None
108+
109+
await conn.close() # Should not raise
110+
111+
assert conn.ready is False

0 commit comments

Comments
 (0)