Skip to content

Commit 5f933dc

Browse files
authored
Merge pull request CloudBotIRC#124 from linuxdaemon/gonzobot+asyncio-threadsafe-wrap
Fix various version compatibility wrappers
2 parents f4a406c + d3f5353 commit 5f933dc

8 files changed

Lines changed: 42 additions & 18 deletions

File tree

cloudbot/__main__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import signal
44
import sys
55
import time
6+
67
# store the original working directory, for use when restarting
7-
from functools import partial
88

99
original_wd = os.path.realpath(".")
1010

@@ -47,9 +47,7 @@ def exit_gracefully(signum, frame):
4747
# we are currently in the process of restarting
4848
stopped_while_restarting = True
4949
else:
50-
_bot.loop.call_soon_threadsafe(
51-
partial(async_util.wrap_future, _bot.stop("Killed (Received SIGINT {})".format(signum)), loop=_bot.loop)
52-
)
50+
async_util.run_coroutine_threadsafe(_bot.stop("Killed (Received SIGINT {})".format(signum)), _bot.loop)
5351

5452
logger.warning("Bot received Signal Interrupt ({})".format(signum))
5553

cloudbot/bot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from cloudbot.hook import Action
2121
from cloudbot.plugin import PluginManager
2222
from cloudbot.reloader import PluginReloader, ConfigReloader
23-
from cloudbot.util import database, formatting
23+
from cloudbot.util import database, formatting, async_util
2424

2525
try:
2626
from cloudbot.web.main import WebInterface
@@ -65,7 +65,7 @@ def __init__(self, loop=asyncio.get_event_loop()):
6565
self.start_time = time.time()
6666
self.running = True
6767
# future which will be called when the bot stopsIf you
68-
self.stopped_future = asyncio.Future(loop=self.loop)
68+
self.stopped_future = async_util.create_future(self.loop)
6969

7070
# stores each bot server connection
7171
self.connections = {}

cloudbot/clients/irc.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import re
55
import ssl
66
from _ssl import PROTOCOL_SSLv23
7+
from functools import partial
78
from ssl import SSLContext
89

910
from cloudbot.client import Client
@@ -141,7 +142,7 @@ def connect(self, timeout=None):
141142
optional_params["local_addr"] = self.local_bind
142143

143144
coro = self.loop.create_connection(
144-
lambda: _IrcProtocol(self), host=self.server, port=self.port, ssl=self.ssl_context, **optional_params
145+
partial(_IrcProtocol, self), host=self.server, port=self.port, ssl=self.ssl_context, **optional_params
145146
)
146147

147148
if timeout is not None:
@@ -292,7 +293,7 @@ def __init__(self, conn):
292293
self._transport = None
293294

294295
# Future that waits until we are connected
295-
self._connected_future = asyncio.Future(loop=self.loop)
296+
self._connected_future = async_util.create_future(self.loop)
296297

297298
def connection_made(self, transport):
298299
self._transport = transport
@@ -304,7 +305,7 @@ def connection_made(self, transport):
304305
def connection_lost(self, exc):
305306
self._connected = False
306307
# create a new connected_future for when we are connected.
307-
self._connected_future = asyncio.Future(loop=self.loop)
308+
self._connected_future = async_util.create_future(self.loop)
308309
if exc is None:
309310
# we've been closed intentionally, so don't reconnect
310311
return
@@ -314,7 +315,7 @@ def connection_lost(self, exc):
314315
def eof_received(self):
315316
self._connected = False
316317
# create a new connected_future for when we are connected.
317-
self._connected_future = asyncio.Future(loop=self.loop)
318+
self._connected_future = async_util.create_future(self.loop)
318319
logger.info("[{}] EOF received.".format(self.conn.name))
319320
async_util.wrap_future(self.conn.connect(), loop=self.loop)
320321
return True

cloudbot/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ def launch(self, hook, event):
597597
self._hook_waiting_queues[key] = queue
598598
assert isinstance(queue, asyncio.Queue)
599599
# create a future to represent this task
600-
future = asyncio.Future()
600+
future = async_util.create_future(self.bot.loop)
601601
queue.put_nowait(future)
602602
# wait until the last task is completed
603603
yield from future

cloudbot/reloader.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import asyncio
22
from abc import ABC
3-
from functools import partial
43
from pathlib import Path
54

65
from watchdog.events import PatternMatchingEventHandler
@@ -47,14 +46,14 @@ def reload(self, path):
4746
"""
4847
path = Path(path).resolve()
4948
if path.exists():
50-
self.bot.loop.call_soon_threadsafe(partial(async_util.wrap_future, self._reload(path), loop=self.bot.loop))
49+
async_util.run_coroutine_threadsafe(self._reload(path), self.bot.loop)
5150

5251
def unload(self, path):
5352
"""
5453
Unloads a module, given its file path. Thread safe.
5554
"""
5655
path = Path(path).resolve()
57-
self.bot.loop.call_soon_threadsafe(partial(async_util.wrap_future, self._unload(path), loop=self.bot.loop))
56+
async_util.run_coroutine_threadsafe(self._unload(path), self.bot.loop)
5857

5958
@asyncio.coroutine
6059
def _reload(self, path):
@@ -112,5 +111,5 @@ def on_moved(self, event):
112111

113112

114113
class ConfigEventHandler(ReloadHandler):
115-
def on_any_event(self, event) -> None:
114+
def on_any_event(self, event):
116115
self.loader.reload(getattr(event, "dest_path", event.src_path))

cloudbot/util/async_util.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,28 @@ def run_func(loop, func, *args, **kwargs):
3131
return (yield from part())
3232
else:
3333
return (yield from loop.run_in_executor(None, part))
34+
35+
36+
def run_coroutine_threadsafe(coro, loop):
37+
"""
38+
Runs a coroutine in a threadsafe manner
39+
:type coro: coroutine
40+
:type loop: asyncio.AbstractEventLoop
41+
"""
42+
if not asyncio.iscoroutine(coro):
43+
raise TypeError('A coroutine object is required')
44+
45+
if sys.version_info < (3, 5, 1):
46+
loop.call_soon_threadsafe(partial(wrap_future, coro, loop=loop))
47+
else:
48+
asyncio.run_coroutine_threadsafe(coro, loop)
49+
50+
51+
def create_future(loop=None):
52+
if loop is None:
53+
loop = asyncio.get_event_loop()
54+
55+
if sys.version_info < (3, 5, 2):
56+
return asyncio.Future(loop=loop)
57+
58+
return loop.create_future()

plugins/core/cap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def handle_available_caps(conn, caplist, event, irc_paramlist, bot):
3030
]
3131
results = yield from asyncio.gather(*tasks)
3232
if any(ok and (res or res is None) for ok, res in results):
33-
cap_queue[name_cf] = conn.loop.create_future()
33+
cap_queue[name_cf] = async_util.create_future(conn.loop)
3434
conn.cmd("CAP", "REQ", cap)
3535

3636
if irc_paramlist[2] != '+':

plugins/sasl.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import base64
33

44
from cloudbot import hook
5+
from cloudbot.util import async_util
56

67

78
@hook.on_cap_available("sasl")
@@ -16,14 +17,14 @@ def sasl_ack(conn, logger):
1617
sasl_auth = conn.config.get('sasl')
1718
if sasl_auth and sasl_auth.get('enabled', True):
1819
sasl_mech = sasl_auth.get("mechanism", "PLAIN").upper()
19-
auth_fut = conn.loop.create_future()
20+
auth_fut = async_util.create_future(conn.loop)
2021
conn.memory["sasl_auth_future"] = auth_fut
2122
conn.cmd("AUTHENTICATE", sasl_mech)
2223
cmd, arg = yield from auth_fut
2324
if cmd == "908":
2425
logger.warning("[%s|sasl] SASL mechanism not supported", conn.name)
2526
elif cmd == "AUTHENTICATE" and arg[0] == '+':
26-
num_fut = conn.loop.create_future()
27+
num_fut = async_util.create_future(conn.loop)
2728
conn.memory["sasl_numeric_future"] = num_fut
2829
if sasl_mech == "PLAIN":
2930
auth_str = "{nick}\0{user}\0{passwd}".format(

0 commit comments

Comments
 (0)