From 982f6707e10e459510fa611fc2d75375f44b1351 Mon Sep 17 00:00:00 2001 From: Bibo-Joshi Date: Mon, 30 Mar 2020 17:37:37 +0200 Subject: [PATCH] Make ConversationHandler attributes immutable (#1756) * Make ConversationHandler attributes immutable * Add forgotten name property to test_immutable --- telegram/ext/conversationhandler.py | 101 +++++++++++++++++++++++++--- tests/test_conversationhandler.py | 32 +++++++++ 2 files changed, 123 insertions(+), 10 deletions(-) diff --git a/telegram/ext/conversationhandler.py b/telegram/ext/conversationhandler.py index 22112f9d0..e922858c3 100644 --- a/telegram/ext/conversationhandler.py +++ b/telegram/ext/conversationhandler.py @@ -165,23 +165,23 @@ class ConversationHandler(Handler): persistent=False, map_to_parent=None): - self.entry_points = entry_points - self.states = states - self.fallbacks = fallbacks + self._entry_points = entry_points + self._states = states + self._fallbacks = fallbacks - self.allow_reentry = allow_reentry - self.per_user = per_user - self.per_chat = per_chat - self.per_message = per_message - self.conversation_timeout = conversation_timeout - self.name = name + self._allow_reentry = allow_reentry + self._per_user = per_user + self._per_chat = per_chat + self._per_message = per_message + self._conversation_timeout = conversation_timeout + self._name = name if persistent and not self.name: raise ValueError("Conversations can't be persistent when handler is unnamed.") self.persistent = persistent self._persistence = None """:obj:`telegram.ext.BasePersistance`: The persistence used to store conversations. Set by dispatcher""" - self.map_to_parent = map_to_parent + self._map_to_parent = map_to_parent self.timeout_jobs = dict() self._timeout_jobs_lock = Lock() @@ -225,6 +225,87 @@ class ConversationHandler(Handler): "since inline queries have no chat context.") break + @property + def entry_points(self): + return self._entry_points + + @entry_points.setter + def entry_points(self, value): + raise ValueError('You can not assign a new value to entry_points after initialization.') + + @property + def states(self): + return self._states + + @states.setter + def states(self, value): + raise ValueError('You can not assign a new value to states after initialization.') + + @property + def fallbacks(self): + return self._fallbacks + + @fallbacks.setter + def fallbacks(self, value): + raise ValueError('You can not assign a new value to fallbacks after initialization.') + + @property + def allow_reentry(self): + return self._allow_reentry + + @allow_reentry.setter + def allow_reentry(self, value): + raise ValueError('You can not assign a new value to allow_reentry after initialization.') + + @property + def per_user(self): + return self._per_user + + @per_user.setter + def per_user(self, value): + raise ValueError('You can not assign a new value to per_user after initialization.') + + @property + def per_chat(self): + return self._per_chat + + @per_chat.setter + def per_chat(self, value): + raise ValueError('You can not assign a new value to per_chat after initialization.') + + @property + def per_message(self): + return self._per_message + + @per_message.setter + def per_message(self, value): + raise ValueError('You can not assign a new value to per_message after initialization.') + + @property + def conversation_timeout(self): + return self._conversation_timeout + + @conversation_timeout.setter + def conversation_timeout(self, value): + raise ValueError('You can not assign a new value to conversation_timeout after ' + 'initialization.') + + @property + def name(self): + return self._name + + @name.setter + def name(self, value): + raise ValueError('You can not assign a new value to name after initialization.') + + @property + def map_to_parent(self): + return self._map_to_parent + + @map_to_parent.setter + def map_to_parent(self, value): + raise ValueError('You can not assign a new value to map_to_parent after initialization.') + @property def persistence(self): return self._persistence diff --git a/tests/test_conversationhandler.py b/tests/test_conversationhandler.py index 4e62a15fa..30a0542b7 100644 --- a/tests/test_conversationhandler.py +++ b/tests/test_conversationhandler.py @@ -179,6 +179,38 @@ class TestConversationHandler(object): return self._set_state(update, self.STOPPING) # Tests + @pytest.mark.parametrize('attr', ['entry_points', 'states', 'fallbacks', 'per_chat', 'name', + 'per_user', 'allow_reentry', 'conversation_timeout', 'map_to_parent'], + indirect=False) + def test_immutable(self, attr): + ch = ConversationHandler('entry_points', {'states': ['states']}, 'fallbacks', + per_chat='per_chat', + per_user='per_user', per_message=False, + allow_reentry='allow_reentry', + conversation_timeout='conversation_timeout', + name='name', map_to_parent='map_to_parent') + + value = getattr(ch, attr) + if isinstance(value, list): + assert value[0] == attr + elif isinstance(value, dict): + assert list(value.keys())[0] == attr + else: + assert getattr(ch, attr) == attr + with pytest.raises(ValueError, match='You can not assign a new value to {}'.format(attr)): + setattr(ch, attr, True) + + def test_immutable_per_message(self): + ch = ConversationHandler('entry_points', {'states': ['states']}, 'fallbacks', + per_chat='per_chat', + per_user='per_user', per_message=False, + allow_reentry='allow_reentry', + conversation_timeout='conversation_timeout', + name='name', map_to_parent='map_to_parent') + assert ch.per_message is False + with pytest.raises(ValueError, match='You can not assign a new value to per_message'): + ch.per_message = True + def test_per_all_false(self): with pytest.raises(ValueError, match="can't all be 'False'"): ConversationHandler(self.entry_points, self.states, self.fallbacks,