Repository: python-telegram-bot/python-telegram-bot

Issue:
Use concrete types instead of iterable
Uses of "Iterable" I found:

* Filters.text (+ tests)
* Filters.caption (+ tests)
* Updater.idle


Discussion:
@Bibo-Joshi we have iterables at jobs?

Resolving patch:
diff --git a/telegram/ext/filters.py b/telegram/ext/filters.py
--- a/telegram/ext/filters.py
+++ b/telegram/ext/filters.py
@@ -236,35 +236,35 @@ def filter(self, message):
     class _Text(BaseFilter):
         name = 'Filters.text'
 
-        class _TextIterable(BaseFilter):
+        class _TextStrings(BaseFilter):
 
-            def __init__(self, iterable):
-                self.iterable = iterable
-                self.name = 'Filters.text({})'.format(iterable)
+            def __init__(self, strings):
+                self.strings = strings
+                self.name = 'Filters.text({})'.format(strings)
 
             def filter(self, message):
                 if message.text:
-                    return message.text in self.iterable
+                    return message.text in self.strings
                 return False
 
         def __call__(self, update):
             if isinstance(update, Update):
                 return self.filter(update.effective_message)
             else:
-                return self._TextIterable(update)
+                return self._TextStrings(update)
 
         def filter(self, message):
             return bool(message.text)
 
     text = _Text()
-    """Text Messages. If an iterable of strings is passed, it filters messages to only allow those
-    whose text is appearing in the given iterable.
+    """Text Messages. If a list of strings is passed, it filters messages to only allow those
+    whose text is appearing in the given list.
 
     Examples:
         To allow any text message, simply use
         ``MessageHandler(Filters.text, callback_method)``.
 
-        A simple usecase for passing an iterable is to allow only messages that were send by a
+        A simple usecase for passing a list is to allow only messages that were send by a
         custom :class:`telegram.ReplyKeyboardMarkup`::
 
             buttons = ['Start', 'Settings', 'Back']
@@ -273,43 +273,43 @@ def filter(self, message):
             MessageHandler(Filters.text(buttons), callback_method)
 
     Args:
-        update (Iterable[:obj:`str`], optional): Which messages to allow. Only exact matches
-            are allowed. If not specified, will allow any text message.
+        update (List[:obj:`str`] | Tuple[:obj:`str`], optional): Which messages to allow. Only
+            exact matches are allowed. If not specified, will allow any text message.
     """
 
     class _Caption(BaseFilter):
         name = 'Filters.caption'
 
-        class _CaptionIterable(BaseFilter):
+        class _CaptionStrings(BaseFilter):
 
-            def __init__(self, iterable):
-                self.iterable = iterable
-                self.name = 'Filters.caption({})'.format(iterable)
+            def __init__(self, strings):
+                self.strings = strings
+                self.name = 'Filters.caption({})'.format(strings)
 
             def filter(self, message):
                 if message.caption:
-                    return message.caption in self.iterable
+                    return message.caption in self.strings
                 return False
 
         def __call__(self, update):
             if isinstance(update, Update):
                 return self.filter(update.effective_message)
             else:
-                return self._CaptionIterable(update)
+                return self._CaptionStrings(update)
 
         def filter(self, message):
             return bool(message.caption)
 
     caption = _Caption()
-    """Messages with a caption. If an iterable of strings is passed, it filters messages to only
-    allow those whose caption is appearing in the given iterable.
+    """Messages with a caption. If a list of strings is passed, it filters messages to only
+    allow those whose caption is appearing in the given list.
 
     Examples:
         ``MessageHandler(Filters.caption, callback_method)``
 
     Args:
-        update (Iterable[:obj:`str`], optional): Which captions to allow. Only exact matches
-            are allowed. If not specified, will allow any message with a caption.
+        update (List[:obj:`str`] | Tuple[:obj:`str`], optional): Which captions to allow. Only
+            exact matches are allowed. If not specified, will allow any message with a caption.
     """
 
     class _Command(BaseFilter):
diff --git a/telegram/ext/updater.py b/telegram/ext/updater.py
--- a/telegram/ext/updater.py
+++ b/telegram/ext/updater.py
@@ -570,9 +570,9 @@ def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
         """Blocks until one of the signals are received and stops the updater.
 
         Args:
-            stop_signals (:obj:`iterable`): Iterable containing signals from the signal module that
-                should be subscribed to. Updater.stop() will be called on receiving one of those
-                signals. Defaults to (``SIGINT``, ``SIGTERM``, ``SIGABRT``).
+            stop_signals (:obj:`list` | :obj:`tuple`): List containing signals from the signal
+                module that should be subscribed to. Updater.stop() will be called on receiving one
+                of those signals. Defaults to (``SIGINT``, ``SIGTERM``, ``SIGABRT``).
 
         """
         for sig in stop_signals:


Test patch:
diff --git a/tests/test_filters.py b/tests/test_filters.py
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -47,7 +47,7 @@ def test_filters_text(self, update):
         update.message.text = '/test'
         assert (Filters.text)(update)
 
-    def test_filters_text_iterable(self, update):
+    def test_filters_text_strings(self, update):
         update.message.text = '/test'
         assert Filters.text({'/test', 'test1'})(update)
         assert not Filters.text(['test1', 'test2'])(update)
@@ -58,7 +58,7 @@ def test_filters_caption(self, update):
         update.message.caption = None
         assert not (Filters.caption)(update)
 
-    def test_filters_caption_iterable(self, update):
+    def test_filters_caption_strings(self, update):
         update.message.caption = 'test'
         assert Filters.caption({'test', 'test1'})(update)
         assert not Filters.caption(['test1', 'test2'])(update)