Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override Bot.__deepcopy__ #3446

Merged
merged 3 commits into from Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/source/telegram.bot.rst
Expand Up @@ -3,4 +3,5 @@ telegram.Bot

.. autoclass:: telegram.Bot
:members:
:show-inheritance:
:show-inheritance:
:special-members: __reduce__, __deepcopy__
24 changes: 22 additions & 2 deletions telegram/_bot.py
Expand Up @@ -140,7 +140,8 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
passing files.
* Bots should not be serialized since if you for e.g. change the bots token, then your
serialized instance will not reflect that change. Trying to pickle a bot instance will
raise :exc:`pickle.PicklingError`.
raise :exc:`pickle.PicklingError`. Trying to deepcopy a bot instance will raise
:exc:`TypeError`.

Examples:
:any:`Raw API Bot <examples.rawapibot>`
Expand All @@ -166,6 +167,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
:class:`telegram.ext.Defaults`, please use the subclass :class:`telegram.ext.ExtBot`
instead.
* Attempting to pickle a bot instance will now raise :exc:`pickle.PicklingError`.
* Attempting to deepcopy a bot instance will now raise :exc:`TypeError`.
* The following are now keyword-only arguments in Bot methods:
``location``, ``filename``, ``venue``, ``contact``,
``{read, write, connect, pool}_timeout``, ``api_kwargs``. Use a named argument for those,
Expand Down Expand Up @@ -299,9 +301,27 @@ def private_key(self) -> Optional[Any]:
return self._private_key

def __reduce__(self) -> NoReturn:
"""Called by pickle.dumps(). Serializing bots is unadvisable, so we forbid pickling."""
"""Customizes how :func:`copy.deepcopy` processes objects of this type. Bots can not
be pickled and this method will always raise an exception.

.. versionadded:: 20.0

Raises:
:exc:`pickle.PicklingError`
"""
raise pickle.PicklingError("Bot objects cannot be pickled!")

def __deepcopy__(self, memodict: dict) -> NoReturn:
"""Customizes how :func:`copy.deepcopy` processes objects of this type. Bots can not
be deepcopied and this method will always raise an exception.

.. versionadded:: 20.0

Raises:
:exc:`TypeError`
"""
raise TypeError("Bot objects cannot be deepcopied!")

# TODO: After https://youtrack.jetbrains.com/issue/PY-50952 is fixed, we can revisit this and
# consider adding Paramspec from typing_extensions to properly fix this. Currently a workaround
def _log(func: Any): # type: ignore[no-untyped-def] # skipcq: PY-D0003
Expand Down
4 changes: 4 additions & 0 deletions tests/test_bot.py
Expand Up @@ -426,6 +426,10 @@ def test_bot_pickling_error(self, bot):
with pytest.raises(pickle.PicklingError, match="Bot objects cannot be pickled"):
pickle.dumps(bot)

def test_bot_deepcopy_error(self, bot):
with pytest.raises(TypeError, match="Bot objects cannot be deepcopied"):
copy.deepcopy(bot)

@bot_methods(ext_bot=False)
async def test_defaults_handling(
self, bot_class, bot_method_name, bot_method, bot, raw_bot, monkeypatch
Expand Down