Skip to content

Warnings overhaul #2662

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

Merged
merged 16 commits into from
Sep 20, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/telegram.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,4 @@ utils
telegram.utils.promise
telegram.utils.request
telegram.utils.types
telegram.utils.warnings
8 changes: 8 additions & 0 deletions docs/source/telegram.utils.warnings.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/utils/warnings.py

telegram.utils.warnings Module
===============================

.. automodule:: telegram.utils.warnings
:members:
:show-inheritance:
12 changes: 7 additions & 5 deletions telegram/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
except ImportError:
import json # type: ignore[no-redef]

import warnings
from typing import TYPE_CHECKING, List, Optional, Type, TypeVar, Tuple

from telegram.utils.types import JSONDict
from telegram.utils.warnings import warn

if TYPE_CHECKING:
from telegram import Bot
Expand Down Expand Up @@ -140,14 +140,16 @@ def __eq__(self, other: object) -> bool:
# pylint: disable=no-member
if isinstance(other, self.__class__):
if self._id_attrs == ():
warnings.warn(
warn(
f"Objects of type {self.__class__.__name__} can not be meaningfully tested for"
" equivalence."
" equivalence.",
stacklevel=2,
)
if other._id_attrs == ():
warnings.warn(
warn(
f"Objects of type {other.__class__.__name__} can not be meaningfully tested"
" for equivalence."
" for equivalence.",
stacklevel=2,
)
return self._id_attrs == other._id_attrs
return super().__eq__(other)
Expand Down
9 changes: 4 additions & 5 deletions telegram/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import functools
import logging
import warnings
from datetime import datetime

from typing import (
Expand Down Expand Up @@ -91,7 +90,7 @@
)
from telegram.constants import MAX_INLINE_QUERY_RESULTS
from telegram.error import InvalidToken, TelegramError
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.warnings import PTBDeprecationWarning, warn
from telegram.utils.helpers import (
DEFAULT_NONE,
DefaultValue,
Expand Down Expand Up @@ -198,10 +197,10 @@ def __init__(
self.defaults = defaults

if self.defaults:
warnings.warn(
warn(
'Passing Defaults to telegram.Bot is deprecated. Use telegram.ext.ExtBot instead.',
TelegramDeprecationWarning,
stacklevel=3,
PTBDeprecationWarning,
stacklevel=4,
)

if base_url is None:
Expand Down
34 changes: 17 additions & 17 deletions telegram/ext/basepersistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the BasePersistence class."""
import warnings
from abc import ABC, abstractmethod
from copy import copy
from typing import Dict, Optional, Tuple, cast, ClassVar, Generic, DefaultDict, NamedTuple
Expand All @@ -26,6 +25,7 @@
import telegram.ext.extbot

from telegram.ext.utils.types import UD, CD, BD, ConversationDict, CDCData
from telegram.utils.warnings import warn, PTBRuntimeWarning


class PersistenceInput(NamedTuple):
Expand Down Expand Up @@ -230,21 +230,21 @@ def _replace_bot(cls, obj: object, memo: Dict[int, object]) -> object: # pylint
return new_immutable
if isinstance(obj, type):
# classes usually do have a __dict__, but it's not writable
warnings.warn(
'BasePersistence.replace_bot does not handle classes. See '
'the docs of BasePersistence.replace_bot for more information.',
RuntimeWarning,
warn(
f'BasePersistence.replace_bot does not handle classes such as {obj.__name__!r}. '
'See the docs of BasePersistence.replace_bot for more information.',
PTBRuntimeWarning,
)
return obj

try:
new_obj = copy(obj)
memo[obj_id] = new_obj
except Exception:
warnings.warn(
warn(
'BasePersistence.replace_bot does not handle objects that can not be copied. See '
'the docs of BasePersistence.replace_bot for more information.',
RuntimeWarning,
PTBRuntimeWarning,
)
memo[obj_id] = obj
return obj
Expand Down Expand Up @@ -282,10 +282,10 @@ def _replace_bot(cls, obj: object, memo: Dict[int, object]) -> object: # pylint
memo[obj_id] = new_obj
return new_obj
except Exception as exception:
warnings.warn(
warn(
f'Parsing of an object failed with the following exception: {exception}. '
f'See the docs of BasePersistence.replace_bot for more information.',
RuntimeWarning,
PTBRuntimeWarning,
)

memo[obj_id] = obj
Expand Down Expand Up @@ -333,20 +333,20 @@ def _insert_bot(self, obj: object, memo: Dict[int, object]) -> object: # pylint
return new_immutable
if isinstance(obj, type):
# classes usually do have a __dict__, but it's not writable
warnings.warn(
'BasePersistence.insert_bot does not handle classes. See '
'the docs of BasePersistence.insert_bot for more information.',
RuntimeWarning,
warn(
f'BasePersistence.insert_bot does not handle classes such as {obj.__name__!r}. '
'See the docs of BasePersistence.insert_bot for more information.',
PTBRuntimeWarning,
)
return obj

try:
new_obj = copy(obj)
except Exception:
warnings.warn(
warn(
'BasePersistence.insert_bot does not handle objects that can not be copied. See '
'the docs of BasePersistence.insert_bot for more information.',
RuntimeWarning,
PTBRuntimeWarning,
)
memo[obj_id] = obj
return obj
Expand Down Expand Up @@ -384,10 +384,10 @@ def _insert_bot(self, obj: object, memo: Dict[int, object]) -> object: # pylint
memo[obj_id] = new_obj
return new_obj
except Exception as exception:
warnings.warn(
warn(
f'Parsing of an object failed with the following exception: {exception}. '
f'See the docs of BasePersistence.insert_bot for more information.',
RuntimeWarning,
PTBRuntimeWarning,
)

memo[obj_id] = obj
Expand Down
41 changes: 23 additions & 18 deletions telegram/ext/conversationhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"""This module contains the ConversationHandler."""

import logging
import warnings
import functools
import datetime
from threading import Lock
Expand All @@ -39,6 +38,7 @@
from telegram.ext.utils.promise import Promise
from telegram.ext.utils.types import ConversationDict
from telegram.ext.utils.types import CCT
from telegram.utils.warnings import warn

if TYPE_CHECKING:
from telegram.ext import Dispatcher, Job
Expand Down Expand Up @@ -259,9 +259,10 @@ def __init__(
raise ValueError("'per_user', 'per_chat' and 'per_message' can't all be 'False'")

if self.per_message and not self.per_chat:
warnings.warn(
warn(
"If 'per_message=True' is used, 'per_chat=True' should also be used, "
"since message IDs are not globally unique."
"since message IDs are not globally unique.",
stacklevel=2,
)

all_handlers: List[Handler] = []
Expand All @@ -274,37 +275,41 @@ def __init__(
if self.per_message:
for handler in all_handlers:
if not isinstance(handler, CallbackQueryHandler):
warnings.warn(
"If 'per_message=True', all entry points and state handlers"
warn(
"If 'per_message=True', all entry points, state handlers, and fallbacks"
" must be 'CallbackQueryHandler', since no other handlers "
"have a message context."
"have a message context.",
stacklevel=2,
)
break
else:
for handler in all_handlers:
if isinstance(handler, CallbackQueryHandler):
warnings.warn(
warn(
"If 'per_message=False', 'CallbackQueryHandler' will not be "
"tracked for every message."
"tracked for every message.",
stacklevel=2,
)
break

if self.per_chat:
for handler in all_handlers:
if isinstance(handler, (InlineQueryHandler, ChosenInlineResultHandler)):
warnings.warn(
warn(
"If 'per_chat=True', 'InlineQueryHandler' can not be used, "
"since inline queries have no chat context."
"since inline queries have no chat context.",
stacklevel=2,
)
break

if self.conversation_timeout:
for handler in all_handlers:
if isinstance(handler, self.__class__):
warnings.warn(
warn(
"Using `conversation_timeout` with nested conversations is currently not "
"supported. You can still try to use it, but it will likely behave "
"differently from what you expect."
"differently from what you expect.",
stacklevel=2,
)
break

Expand Down Expand Up @@ -644,8 +649,8 @@ def handle_update( # type: ignore[override]
new_state, dispatcher, update, context, conversation_key
)
else:
self.logger.warning(
"Ignoring `conversation_timeout` because the Dispatcher has no JobQueue."
warn(
"Ignoring `conversation_timeout` because the Dispatcher has no JobQueue.",
)

if isinstance(self.map_to_parent, dict) and new_state in self.map_to_parent:
Expand Down Expand Up @@ -680,9 +685,9 @@ def _update_state(self, new_state: object, key: Tuple[int, ...]) -> None:

elif new_state is not None:
if new_state not in self.states:
warnings.warn(
warn(
f"Handler returned state {new_state} which is unknown to the "
f"ConversationHandler{' ' + self.name if self.name is not None else ''}."
f"ConversationHandler{' ' + self.name if self.name is not None else ''}.",
)
with self._conversations_lock:
self.conversations[key] = new_state
Expand Down Expand Up @@ -711,9 +716,9 @@ def _trigger_timeout(self, context: CallbackContext) -> None:
try:
handler.handle_update(ctxt.update, ctxt.dispatcher, check, callback_context)
except DispatcherHandlerStop:
self.logger.warning(
warn(
'DispatcherHandlerStop in TIMEOUT state of '
'ConversationHandler has no effect. Ignoring.'
'ConversationHandler has no effect. Ignoring.',
)

self._update_state(self.END, ctxt.conversation_key)
13 changes: 7 additions & 6 deletions telegram/ext/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"""This module contains the Dispatcher class."""

import logging
import warnings
import weakref
from collections import defaultdict
from queue import Empty, Queue
Expand Down Expand Up @@ -47,6 +46,7 @@
import telegram.ext.extbot
from telegram.ext.callbackdatacache import CallbackDataCache
from telegram.ext.utils.promise import Promise
from telegram.utils.warnings import warn
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from telegram.ext.utils.types import CCT, UD, CD, BD

Expand Down Expand Up @@ -196,8 +196,9 @@ def __init__(
self.context_types = cast(ContextTypes[CCT, UD, CD, BD], context_types or ContextTypes())

if self.workers < 1:
warnings.warn(
'Asynchronous callbacks can not be processed without at least one worker thread.'
warn(
'Asynchronous callbacks can not be processed without at least one worker thread.',
stacklevel=2,
)

self.user_data: DefaultDict[int, UD] = defaultdict(self.context_types.user_data)
Expand Down Expand Up @@ -312,9 +313,9 @@ def _pooled(self) -> None:
continue

if isinstance(promise.exception, DispatcherHandlerStop):
self.logger.warning(
'DispatcherHandlerStop is not supported with async functions; func: %s',
promise.pooled_function.__name__,
warn(
'DispatcherHandlerStop is not supported with async functions; '
f'func: {promise.pooled_function.__name__}',
)
continue

Expand Down
23 changes: 12 additions & 11 deletions telegram/ext/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import logging
import ssl
import warnings
from queue import Queue
from signal import SIGABRT, SIGINT, SIGTERM, signal
from threading import Event, Lock, Thread, current_thread
Expand All @@ -42,7 +41,7 @@
from telegram import Bot, TelegramError
from telegram.error import InvalidToken, RetryAfter, TimedOut, Unauthorized
from telegram.ext import Dispatcher, JobQueue, ContextTypes, ExtBot
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.warnings import PTBDeprecationWarning, warn
from telegram.utils.helpers import get_signal_name, DEFAULT_FALSE, DefaultValue
from telegram.utils.request import Request
from telegram.ext.utils.types import CCT, UD, CD, BD
Expand Down Expand Up @@ -211,14 +210,14 @@ def __init__( # type: ignore[no-untyped-def,misc]
):

if defaults and bot:
warnings.warn(
warn(
'Passing defaults to an Updater has no effect when a Bot is passed '
'as well. Pass them to the Bot instead.',
TelegramDeprecationWarning,
PTBDeprecationWarning,
stacklevel=2,
)
if arbitrary_callback_data is not DEFAULT_FALSE and bot:
warnings.warn(
warn(
'Passing arbitrary_callback_data to an Updater has no '
'effect when a Bot is passed as well. Pass them to the Bot instead.',
stacklevel=2,
Expand Down Expand Up @@ -250,9 +249,10 @@ def __init__( # type: ignore[no-untyped-def,misc]
if bot is not None:
self.bot = bot
if bot.request.con_pool_size < con_pool_size:
self.logger.warning(
'Connection pool of Request object is smaller than optimal value (%s)',
con_pool_size,
warn(
f'Connection pool of Request object is smaller than optimal value '
f'{con_pool_size}',
stacklevel=2,
)
else:
# we need a connection pool the size of:
Expand Down Expand Up @@ -299,9 +299,10 @@ def __init__( # type: ignore[no-untyped-def,misc]

self.bot = dispatcher.bot
if self.bot.request.con_pool_size < con_pool_size:
self.logger.warning(
'Connection pool of Request object is smaller than optimal value (%s)',
con_pool_size,
warn(
f'Connection pool of Request object is smaller than optimal value '
f'{con_pool_size}',
stacklevel=2,
)
self.update_queue = dispatcher.update_queue
self.__exception_event = dispatcher.exception_event
Expand Down
Loading