From eb4d58bec179a455916eb212be3076e577e3defe Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 13 Jun 2016 14:15:15 +0300 Subject: [PATCH 1/3] little optimization on handler dictionary building: code duplication lessened --- telebot/__init__.py | 58 +++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 2265897..4e3102f 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -654,6 +654,12 @@ class TeleBot: self.message_subscribers_next_step[k] = self.pre_message_subscribers_next_step[k] self.pre_message_subscribers_next_step = {} + def _build_handler_dict(self, handler, **filters): + return { + 'function': handler, + 'filters': filters + } + def message_handler(self, commands=None, regexp=None, func=None, content_types=['text']): """ Message handler decorator. @@ -685,54 +691,34 @@ class TeleBot: """ def decorator(handler): - self.add_message_handler(handler, commands, regexp, func, content_types) + handler_dict = self._build_handler_dict(handler, + commands=commands, + regexp=regexp, + func=func, + content_types=content_types) + + self.add_message_handler(handler_dict) + return handler return decorator - def add_message_handler(self, handler, commands=None, regexp=None, func=None, content_types=None): - if content_types is None: - content_types = ['text'] - - filters = {'content_types': content_types} - if regexp: - filters['regexp'] = regexp - if func: - filters['lambda'] = func - if commands: - filters['commands'] = commands - - handler_dict = { - 'function': handler, - 'filters': filters - } - + def add_message_handler(self, handler_dict): self.message_handlers.append(handler_dict) def edited_message_handler(self, commands=None, regexp=None, func=None, content_types=['text']): def decorator(handler): - self.add_edited_message_handler(handler, commands, regexp, func, content_types) + handler_dict = self._build_handler_dict(handler, + commands=commands, + regexp=regexp, + func=func, + content_types=content_types) + self.add_edited_message_handler(handler_dict) return handler return decorator - def add_edited_message_handler(self, handler, commands=None, regexp=None, func=None, content_types=None): - if content_types is None: - content_types = ['text'] - - filters = {'content_types': content_types} - if regexp: - filters['regexp'] = regexp - if func: - filters['lambda'] = func - if commands: - filters['commands'] = commands - - handler_dict = { - 'function': handler, - 'filters': filters - } - + def add_edited_message_handler(self, handler_dict): self.edited_message_handlers.append(handler_dict) def inline_handler(self, func): From 1b47e5cc629ebfa50646a01178833aa073428887 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 13 Jun 2016 14:24:27 +0300 Subject: [PATCH 2/3] code duplication lessened --- telebot/__init__.py | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4e3102f..18e6265 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -723,52 +723,34 @@ class TeleBot: def inline_handler(self, func): def decorator(handler): - self.add_inline_handler(handler, func) + handler_dict = self._build_handler_dict(handler, func=func) + self.add_inline_handler(handler_dict) return handler return decorator - def add_inline_handler(self, handler, func): - filters = {'lambda': func} - - handler_dict = { - 'function': handler, - 'filters': filters - } - + def add_inline_handler(self, handler_dict): self.inline_handlers.append(handler_dict) def chosen_inline_handler(self, func): def decorator(handler): - self.add_chosen_inline_handler(handler, func) + handler_dict = self._build_handler_dict(handler, func=func) + self.add_chosen_inline_handler(handler_dict) return handler return decorator - def add_chosen_inline_handler(self, handler, func): - filters = {'lambda': func} - - handler_dict = { - 'function': handler, - 'filters': filters - } - + def add_chosen_inline_handler(self, handler_dict): self.chosen_inline_handlers.append(handler_dict) def callback_query_handler(self, func): def decorator(handler): - self.add_callback_query_handler(handler, func) + handler_dict = self._build_handler_dict(handler, func=func) + self.add_callback_query_handler(handler_dict) return decorator - def add_callback_query_handler(self, handler, func): - filters = {'lambda': func} - - handler_dict = { - 'function': handler, - 'filters': filters - } - + def add_callback_query_handler(self, handler_dict): self.callback_query_handlers.append(handler_dict) @staticmethod @@ -786,7 +768,7 @@ class TeleBot: return message.content_type == 'text' and re.search(filter_value, message.text) if filter == 'commands': return message.content_type == 'text' and util.extract_command(message.text) in filter_value - if filter == 'lambda': + if filter == 'func': return filter_value(message) return False From 527351385be7dfd0c5d471d83381308299e1beee Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 13 Jun 2016 16:47:15 +0300 Subject: [PATCH 3/3] + Don't check filters against NoneType values; + More flexibility for subclassing: - __exec_task is protected now(was private) - _test_message_handler and _test_filter are class members now(used to be static methods) + More flexibility on extention of message_handler(**kwargs for additional parameters) --- telebot/__init__.py | 47 ++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 18e6265..4b86c06 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -174,7 +174,7 @@ class TeleBot: def __notify_update(self, new_messages): for listener in self.update_listener: - self.__exec_task(listener, new_messages) + self._exec_task(listener, new_messages) def polling(self, none_stop=False, interval=0, timeout=20): """ @@ -260,7 +260,7 @@ class TeleBot: logger.info('Stopped polling.') - def __exec_task(self, task, *args, **kwargs): + def _exec_task(self, task, *args, **kwargs): if self.threaded: self.worker_pool.put(task, *args, **kwargs) else: @@ -643,7 +643,7 @@ class TeleBot: if chat_id in self.message_subscribers_next_step: handlers = self.message_subscribers_next_step[chat_id] for handler in handlers: - self.__exec_task(handler, message) + self._exec_task(handler, message) self.message_subscribers_next_step.pop(chat_id, None) def _append_pre_next_step_handler(self): @@ -660,7 +660,7 @@ class TeleBot: 'filters': filters } - def message_handler(self, commands=None, regexp=None, func=None, content_types=['text']): + def message_handler(self, commands=None, regexp=None, func=None, content_types=['text'], **kwargs): """ Message handler decorator. This decorator can be used to decorate functions that must handle certain types of messages. @@ -695,7 +695,8 @@ class TeleBot: commands=commands, regexp=regexp, func=func, - content_types=content_types) + content_types=content_types, + **kwargs) self.add_message_handler(handler_dict) @@ -706,13 +707,14 @@ class TeleBot: def add_message_handler(self, handler_dict): self.message_handlers.append(handler_dict) - def edited_message_handler(self, commands=None, regexp=None, func=None, content_types=['text']): + def edited_message_handler(self, commands=None, regexp=None, func=None, content_types=['text'], **kwargs): def decorator(handler): handler_dict = self._build_handler_dict(handler, commands=commands, regexp=regexp, func=func, - content_types=content_types) + content_types=content_types, + **kwargs) self.add_edited_message_handler(handler_dict) return handler @@ -753,30 +755,31 @@ class TeleBot: def add_callback_query_handler(self, handler_dict): self.callback_query_handlers.append(handler_dict) - @staticmethod - def _test_message_handler(message_handler, message): + def _test_message_handler(self, message_handler, message): for filter, filter_value in six.iteritems(message_handler['filters']): - if not TeleBot._test_filter(filter, filter_value, message): + if filter_value is None: + continue + + if not self._test_filter(filter, filter_value, message): return False + return True - @staticmethod - def _test_filter(filter, filter_value, message): - if filter == 'content_types': - return message.content_type in filter_value - if filter == 'regexp': - return message.content_type == 'text' and re.search(filter_value, message.text) - if filter == 'commands': - return message.content_type == 'text' and util.extract_command(message.text) in filter_value - if filter == 'func': - return filter_value(message) - return False + def _test_filter(self, filter, filter_value, message): + test_cases = { + 'content_types': lambda msg: msg.content_type in filter_value, + 'regexp': lambda msg: msg.content_type == 'text' and re.search(filter_value, msg.text), + 'commands': lambda msg: msg.content_type == 'text' and util.extract_command(msg.text) in filter_value, + 'func': lambda msg: filter_value(msg) + } + + return test_cases.get(filter, lambda msg: False)(message) def _notify_command_handlers(self, handlers, new_messages): for message in new_messages: for message_handler in handlers: if self._test_message_handler(message_handler, message): - self.__exec_task(message_handler['function'], message) + self._exec_task(message_handler['function'], message) break