Skip to content

Commit 3f7992f

Browse files
authored
Merge pull request #128 from Shizmob/develop
Release 0.9.3
2 parents b60e22d + 87c4e74 commit 3f7992f

File tree

5 files changed

+39
-36
lines changed

5 files changed

+39
-36
lines changed

pydle/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from asyncio import coroutine, Future
99

1010
__name__ = 'pydle'
11-
__version__ = '0.9.2'
12-
__version_info__ = (0, 9, 2)
11+
__version__ = '0.9.3'
12+
__version_info__ = (0, 9, 3)
1313
__license__ = 'BSD'
1414

1515

pydle/client.py

+31-31
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from asyncio import new_event_loop, gather, get_event_loop, sleep
66

77
from . import connection, protocol
8+
import warnings
89

910
__all__ = ['Error', 'AlreadyInChannel', 'NotInChannel', 'BasicClient', 'ClientPool']
1011
DEFAULT_NICKNAME = '<unregistered>'
@@ -32,12 +33,29 @@ class BasicClient:
3233
Base IRC client class.
3334
This class on its own is not complete: in order to be able to run properly, _has_message, _parse_message and _create_message have to be overloaded.
3435
"""
35-
PING_TIMEOUT = 300
36+
READ_TIMEOUT = 300
3637
RECONNECT_ON_ERROR = True
3738
RECONNECT_MAX_ATTEMPTS = 3
3839
RECONNECT_DELAYED = True
3940
RECONNECT_DELAYS = [5, 5, 10, 30, 120, 600]
4041

42+
@property
43+
def PING_TIMEOUT(self):
44+
warnings.warn(
45+
"PING_TIMEOUT has been moved to READ_TIMEOUT and may be removed in a future version. "
46+
"Please migrate to READ_TIMEOUT.",
47+
DeprecationWarning
48+
)
49+
return self.READ_TIMEOUT
50+
51+
@PING_TIMEOUT.setter
52+
def PING_TIMEOUT(self, value):
53+
warnings.warn(
54+
"PING_TIMEOUT has been moved to READ_TIMEOUT and may be removed in a future version",
55+
DeprecationWarning
56+
)
57+
self.READ_TIMEOUT = value
58+
4159
def __init__(self, nickname, fallback_nicknames=[], username=None, realname=None,
4260
eventloop=None, **kwargs):
4361
""" Create a client. """
@@ -66,7 +84,6 @@ def _reset_attributes(self):
6684
self._receive_buffer = b''
6785
self._pending = {}
6886
self._handler_top_level = False
69-
self._ping_checker_handle = None
7087

7188
# Misc.
7289
self.logger = logging.getLogger(__name__)
@@ -115,10 +132,6 @@ async def connect(self, hostname=None, port=None, reconnect=False, **kwargs):
115132
async def disconnect(self, expected=True):
116133
""" Disconnect from server. """
117134
if self.connected:
118-
# Unschedule ping checker.
119-
if self._ping_checker_handle:
120-
self._ping_checker_handle.cancel()
121-
122135
# Schedule disconnect.
123136
await self._disconnect(expected)
124137

@@ -159,21 +172,6 @@ def _reconnect_delay(self):
159172
else:
160173
return 0
161174

162-
async def _perform_ping_timeout(self, delay: int):
163-
""" Handle timeout gracefully.
164-
165-
Args:
166-
delay (int): delay before raising the timeout (in seconds)
167-
"""
168-
169-
# pause for delay seconds
170-
await sleep(delay)
171-
# then continue
172-
error = TimeoutError(
173-
'Ping timeout: no data received from server in {timeout} seconds.'.format(
174-
timeout=self.PING_TIMEOUT))
175-
await self.on_data_error(error)
176-
177175
## Internal database management.
178176

179177
def _create_channel(self, channel):
@@ -365,7 +363,18 @@ async def _send(self, input):
365363
async def handle_forever(self):
366364
""" Handle data forever. """
367365
while self.connected:
368-
data = await self.connection.recv()
366+
try:
367+
data = await self.connection.recv(timeout=self.READ_TIMEOUT)
368+
except asyncio.TimeoutError:
369+
self.logger.warning(
370+
'>> Receive timeout reached, sending ping to check connection state...')
371+
372+
try:
373+
await self.rawmsg("PING", self.server_tag)
374+
data = await self.connection.recv(timeout=self.READ_TIMEOUT)
375+
except asyncio.TimeoutError:
376+
data = None
377+
369378
if not data:
370379
if self.connected:
371380
await self.disconnect(expected=False)
@@ -378,19 +387,10 @@ async def on_data(self, data):
378387
""" Handle received data. """
379388
self._receive_buffer += data
380389

381-
# Schedule new timeout event.
382-
if self._ping_checker_handle:
383-
self._ping_checker_handle.cancel()
384-
385-
# create a task for the ping checker
386-
self._ping_checker_handle = self.eventloop.create_task(
387-
self._perform_ping_timeout(self.PING_TIMEOUT))
388-
389390
while self._has_message():
390391
message = self._parse_message()
391392
self.eventloop.create_task(self.on_raw(message))
392393

393-
394394
async def on_data_error(self, exception):
395395
""" Handle error. """
396396
self.logger.error('Encountered error on socket.',

pydle/connection.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,5 @@ async def send(self, data):
127127
self.writer.write(data)
128128
await self.writer.drain()
129129

130-
async def recv(self):
131-
return await self.reader.readline()
130+
async def recv(self, *, timeout=None):
131+
return await asyncio.wait_for(self.reader.readline(), timeout=timeout)

pydle/features/rfc1459/client.py

+3
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,9 @@ async def on_raw_error(self, message):
541541
error = protocol.ServerError(' '.join(message.params))
542542
await self.on_data_error(error)
543543

544+
async def on_raw_pong(self, message):
545+
self.logger.debug('>> PONG received')
546+
544547
async def on_raw_invite(self, message):
545548
""" INVITE command. """
546549
nick, metadata = self._parse_user(message.source)

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='pydle',
5-
version='0.9.2',
5+
version='0.9.3',
66
python_requires=">=3.5",
77
packages=[
88
'pydle',

0 commit comments

Comments
 (0)