Skip to content

Commit c15a1bc

Browse files
committed
1 parent 9e73141 commit c15a1bc

File tree

3 files changed

+58
-19
lines changed

3 files changed

+58
-19
lines changed

examples/updater_bot.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,15 @@ def unknown_command(bot, update):
6565

6666

6767
@run_async
68-
def message(bot, update):
68+
def message(bot, update, **kwargs):
6969
"""
7070
Example for an asynchronous handler. It's not guaranteed that replies will
71-
be in order when using @run_async.
71+
be in order when using @run_async. Also, you have to include **kwargs in
72+
your parameter list.
7273
"""
7374

75+
print(kwargs)
76+
7477
sleep(2) # IO-heavy operation here
7578
bot.sendMessage(update.message.chat_id, text='Echo: %s' %
7679
update.message.text)

telegram/dispatcher.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121

2222
def run_async(func):
2323
"""
24-
Function decorator that will run the function in a new thread.
24+
Function decorator that will run the function in a new thread. A function
25+
decorated with this will have to include **kwargs in their parameter list,
26+
which will contain all optional parameters.
2527
2628
Args:
2729
func (function): The function to run in the thread.
@@ -31,24 +33,24 @@ def run_async(func):
3133
"""
3234

3335
@wraps(func)
34-
def pooled(*args, **kwargs):
36+
def pooled(*pargs, **kwargs):
3537
"""
3638
A wrapper to run a thread in a thread pool
3739
"""
3840
global running_async, async_lock
39-
result = func(*args, **kwargs)
41+
result = func(*pargs, **kwargs)
4042
semaphore.release()
4143
with async_lock:
4244
running_async -= 1
4345
return result
4446

4547
@wraps(func)
46-
def async_func(*args, **kwargs):
48+
def async_func(*pargs, **kwargs):
4749
"""
4850
A wrapper to run a function in a thread
4951
"""
5052
global running_async, async_lock
51-
thread = Thread(target=pooled, args=args, kwargs=kwargs)
53+
thread = Thread(target=pooled, args=pargs, kwargs=kwargs)
5254
semaphore.acquire()
5355
with async_lock:
5456
running_async += 1
@@ -509,8 +511,7 @@ def dispatchStringRegex(self, update):
509511
510512
Args:
511513
command (str): The command keyword
512-
update (telegram.Update): The Telegram update that contains the
513-
command
514+
update (str): The string that contains the command
514515
"""
515516

516517
matching_handlers = []
@@ -560,7 +561,7 @@ def dispatchError(self, update, error):
560561
for handler in self.error_handlers:
561562
handler(self.bot, update, error)
562563

563-
def dispatchTo(self, handlers, update):
564+
def dispatchTo(self, handlers, update, **kwargs):
564565
"""
565566
Dispatches an update to a list of handlers.
566567
@@ -570,9 +571,9 @@ def dispatchTo(self, handlers, update):
570571
"""
571572

572573
for handler in handlers:
573-
self.call_handler(handler, update)
574+
self.call_handler(handler, update, **kwargs)
574575

575-
def call_handler(self, handler, update):
576+
def call_handler(self, handler, update, **kwargs):
576577
"""
577578
Calls an update handler. Checks the handler for keyword arguments and
578579
fills them, if possible.
@@ -581,20 +582,34 @@ def call_handler(self, handler, update):
581582
handler (function): An update handler function
582583
update (any): An update
583584
"""
584-
kwargs = {}
585+
586+
target_kwargs = {}
585587
fargs = getargspec(handler).args
586588

587-
if 'update_queue' in fargs:
588-
kwargs['update_queue'] = self.update_queue
589+
'''
590+
async handlers will receive all optional arguments, since we can't
591+
their argument list.
592+
'''
593+
594+
is_async = 'pargs' == getargspec(handler).varargs
589595

590-
if 'args' in fargs:
596+
if is_async or 'update_queue' in fargs:
597+
target_kwargs['update_queue'] = self.update_queue
598+
599+
if is_async or 'args' in fargs:
591600
if isinstance(update, Update):
592601
args = update.message.text.split(' ')[1:]
593602
elif isinstance(update, str):
594603
args = update.split(' ')[1:]
595604
else:
596605
args = None
597606

598-
kwargs['args'] = args
607+
target_kwargs['args'] = args
608+
609+
if is_async or 'groups' in fargs:
610+
target_kwargs['groups'] = kwargs.get('groups', None)
611+
612+
if is_async or 'groupdict' in fargs:
613+
target_kwargs['groupdict'] = kwargs.get('groupdict', None)
599614

600-
handler(self.bot, update, **kwargs)
615+
handler(self.bot, update, **target_kwargs)

tests/test_updater.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def telegramHandlerTest(self, bot, update):
7979
self.message_count += 1
8080

8181
@run_async
82-
def asyncHandlerTest(self, bot, update):
82+
def asyncHandlerTest(self, bot, update, **kwargs):
8383
sleep(1)
8484
with self.lock:
8585
self.received_message = update.message.text
@@ -97,6 +97,15 @@ def additionalArgsTest(self, bot, update, update_queue, args):
9797
elif args[0] == 'noresend':
9898
pass
9999

100+
@run_async
101+
def asyncAdditionalHandlerTest(self, bot, update, update_queue=None,
102+
**kwargs):
103+
sleep(1)
104+
with self.lock:
105+
if update_queue is not None:
106+
self.received_message = update.message.text
107+
self.message_count += 1
108+
100109
def errorRaisingHandlerTest(self, bot, update):
101110
raise TelegramError(update)
102111

@@ -339,6 +348,18 @@ def test_additionalArgs(self):
339348
self.assertEqual(self.received_message, '/test5 noresend')
340349
self.assertEqual(self.message_count, 2)
341350

351+
def test_runAsyncWithAdditionalArgs(self):
352+
print('Testing @run_async with additional parameters')
353+
bot = MockBot('Test6', messages=2)
354+
self.updater.bot = bot
355+
d = self.updater.dispatcher
356+
d.addTelegramMessageHandler(
357+
self.asyncAdditionalHandlerTest)
358+
self.updater.start_polling(0.01)
359+
sleep(1.2)
360+
self.assertEqual(self.received_message, 'Test6')
361+
self.assertEqual(self.message_count, 2)
362+
342363
def test_webhook(self):
343364
print('Testing Webhook')
344365
bot = MockBot('', messages=0)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy