diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 199f72a5a..46634a6d8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,18 +9,18 @@ ci: repos: - repo: https://github.com/psf/black - rev: 22.6.0 + rev: 22.8.0 hooks: - id: black args: - --diff - --check - repo: https://github.com/PyCQA/flake8 - rev: 5.0.2 + rev: 5.0.4 hooks: - id: flake8 - repo: https://github.com/PyCQA/pylint - rev: v2.13.9 + rev: v2.15.2 hooks: - id: pylint files: ^(telegram|examples)/.*\.py$ diff --git a/pyproject.toml b/pyproject.toml index 9184b0427..8b29b136d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.black] line-length = 99 -target-version = ['py37', 'py38', 'py39', 'py310'] +target-version = ['py37', 'py38', 'py39', 'py310', 'py311'] [tool.isort] # black config profile = "black" diff --git a/telegram/_bot.py b/telegram/_bot.py index b397bb615..1b8e5e87a 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -246,7 +246,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager): return decorator - def _insert_defaults(self, data: Dict[str, object]) -> None: # pylint: disable=no-self-use + def _insert_defaults(self, data: Dict[str, object]) -> None: # skipcq: PYL-R0201 """This method is here to make ext.Defaults work. Because we need to be able to tell e.g. `send_message(chat_id, text)` from `send_message(chat_id, text, parse_mode=None)`, the default values for `parse_mode` etc are not `None` but `DEFAULT_NONE`. While this *could* @@ -2724,7 +2724,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager): ) return result # type: ignore[return-value] - def _effective_inline_results( # pylint: disable=no-self-use + def _effective_inline_results( # skipcq: PYL-R0201 self, results: Union[ Sequence["InlineQueryResult"], Callable[[int], Optional[Sequence["InlineQueryResult"]]] @@ -2781,9 +2781,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager): return effective_results, next_offset @no_type_check # mypy doesn't play too well with hasattr - def _insert_defaults_for_ilq_results( # pylint: disable=no-self-use - self, res: "InlineQueryResult" - ) -> None: + def _insert_defaults_for_ilq_results(self, res: "InlineQueryResult") -> None: """The reason why this method exists is similar to the description of _insert_defaults The reason why we do this in rather than in _insert_defaults is because converting DEFAULT_NONE to NONE *before* calling to_dict() makes it way easier to drop None entries diff --git a/telegram/_telegramobject.py b/telegram/_telegramobject.py index a4c9e2f35..515319594 100644 --- a/telegram/_telegramobject.py +++ b/telegram/_telegramobject.py @@ -27,7 +27,7 @@ from telegram._utils.warnings import warn if TYPE_CHECKING: from telegram import Bot -TO_co = TypeVar("TO_co", bound="TelegramObject", covariant=True) +Tele_co = TypeVar("Tele_co", bound="TelegramObject", covariant=True) class TelegramObject: @@ -96,7 +96,7 @@ class TelegramObject: for key, val in state.items(): setattr(self, key, val) - def __deepcopy__(self: TO_co, memodict: dict) -> TO_co: + def __deepcopy__(self: Tele_co, memodict: dict) -> Tele_co: """This method deepcopies the object and sets the bot on the newly created copy.""" bot = self._bot # Save bot so we can set it after copying self.set_bot(None) # set to None so it is not deepcopied @@ -149,7 +149,7 @@ class TelegramObject: value = getattr(self, key, None) if value is not None: if recursive and hasattr(value, "to_dict"): - data[key] = value.to_dict() + data[key] = value.to_dict() # pylint: disable=no-member else: data[key] = value elif not recursive: @@ -166,7 +166,7 @@ class TelegramObject: return None if data is None else data.copy() @classmethod - def de_json(cls: Type[TO_co], data: Optional[JSONDict], bot: "Bot") -> Optional[TO_co]: + def de_json(cls: Type[Tele_co], data: Optional[JSONDict], bot: "Bot") -> Optional[Tele_co]: """Converts JSON data to a Telegram object. Args: @@ -188,8 +188,8 @@ class TelegramObject: @classmethod def de_list( - cls: Type[TO_co], data: Optional[List[JSONDict]], bot: "Bot" - ) -> List[Optional[TO_co]]: + cls: Type[Tele_co], data: Optional[List[JSONDict]], bot: "Bot" + ) -> List[Optional[Tele_co]]: """Converts JSON data to a list of Telegram objects. Args: @@ -251,13 +251,13 @@ class TelegramObject: def __eq__(self, other: object) -> bool: if isinstance(other, self.__class__): - if self._id_attrs == (): + if not self._id_attrs: warn( f"Objects of type {self.__class__.__name__} can not be meaningfully tested for" " equivalence.", stacklevel=2, ) - if other._id_attrs == (): + if not other._id_attrs: warn( f"Objects of type {other.__class__.__name__} can not be meaningfully tested" " for equivalence.", diff --git a/telegram/constants.py b/telegram/constants.py index db3c072fa..b3f4e9c5c 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -28,6 +28,8 @@ those classes. * Most of the constants in this module are grouped into enums. """ +# TODO: Remove this when https://github.com/PyCQA/pylint/issues/6887 is resolved. +# pylint: disable=invalid-enum-extension __all__ = [ "BOT_API_VERSION", diff --git a/telegram/ext/_basepersistence.py b/telegram/ext/_basepersistence.py index 6c2901529..b70f1794f 100644 --- a/telegram/ext/_basepersistence.py +++ b/telegram/ext/_basepersistence.py @@ -161,7 +161,7 @@ class BasePersistence(Generic[UD, CD, BD], ABC): return self._update_interval @update_interval.setter - def update_interval(self, value: object) -> NoReturn: # pylint: disable=no-self-use + def update_interval(self, value: object) -> NoReturn: raise AttributeError( "You can not assign a new value to update_interval after initialization." ) diff --git a/telegram/ext/_callbackcontext.py b/telegram/ext/_callbackcontext.py index e3331f532..d2315726f 100644 --- a/telegram/ext/_callbackcontext.py +++ b/telegram/ext/_callbackcontext.py @@ -16,7 +16,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/]. -# pylint: disable=no-self-use """This module contains the CallbackContext class.""" from typing import TYPE_CHECKING, Coroutine, Dict, Generic, List, Match, NoReturn, Optional, Type diff --git a/telegram/ext/_conversationhandler.py b/telegram/ext/_conversationhandler.py index 715dac72e..33db09de3 100644 --- a/telegram/ext/_conversationhandler.py +++ b/telegram/ext/_conversationhandler.py @@ -16,13 +16,12 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -# pylint: disable=no-self-use """This module contains the ConversationHandler.""" import asyncio import datetime import logging from dataclasses import dataclass -from typing import ( # pylint: disable=unused-import # for the "Any" import +from typing import ( TYPE_CHECKING, Any, ClassVar, diff --git a/telegram/ext/_defaults.py b/telegram/ext/_defaults.py index 0636322da..17c380a11 100644 --- a/telegram/ext/_defaults.py +++ b/telegram/ext/_defaults.py @@ -16,7 +16,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/]. -# pylint: disable=no-self-use """This module contains the class Defaults, which allows passing default values to Application.""" from typing import Any, Dict, NoReturn, Optional diff --git a/telegram/ext/_picklepersistence.py b/telegram/ext/_picklepersistence.py index e08bce5d8..5975012f7 100644 --- a/telegram/ext/_picklepersistence.py +++ b/telegram/ext/_picklepersistence.py @@ -34,10 +34,10 @@ from telegram.ext._utils.types import BD, CD, UD, CDCData, ConversationDict, Con _REPLACED_KNOWN_BOT = "a known bot replaced by PTB's PicklePersistence" _REPLACED_UNKNOWN_BOT = "an unknown bot replaced by PTB's PicklePersistence" -TO = TypeVar("TO", bound=TelegramObject) +TelegramObj = TypeVar("TelegramObj", bound=TelegramObject) -def _all_subclasses(cls: Type[TO]) -> Set[Type[TO]]: +def _all_subclasses(cls: Type[TelegramObj]) -> Set[Type[TelegramObj]]: """Gets all subclasses of the specified object, recursively. from https://stackoverflow.com/a/3862957/9706202 """ @@ -45,7 +45,7 @@ def _all_subclasses(cls: Type[TO]) -> Set[Type[TO]]: return set(subclasses).union([s for c in subclasses for s in _all_subclasses(c)]) -def _reconstruct_to(cls: Type[TO], kwargs: dict) -> TO: +def _reconstruct_to(cls: Type[TelegramObj], kwargs: dict) -> TelegramObj: """ This method is used for unpickling. The data, which is in the form a dictionary, is converted back into a class. Works mostly the same as :meth:`TelegramObject.__setstate__`. @@ -57,7 +57,7 @@ def _reconstruct_to(cls: Type[TO], kwargs: dict) -> TO: return obj # type: ignore[return-value] -def _custom_reduction(cls: TO) -> Tuple[Callable, Tuple[Type[TO], dict]]: +def _custom_reduction(cls: TelegramObj) -> Tuple[Callable, Tuple[Type[TelegramObj], dict]]: """ This method is used for pickling. The bot attribute is preserved so _BotPickler().persistent_id works as intended. @@ -80,9 +80,9 @@ class _BotPickler(pickle.Pickler): self.dispatch_table[obj] = _custom_reduction super().__init__(*args, **kwargs) - def reducer_override( # pylint: disable=no-self-use - self, obj: TO - ) -> Tuple[Callable, Tuple[Type[TO], dict]]: + def reducer_override( # skipcq: PYL-R0201 + self, obj: TelegramObj + ) -> Tuple[Callable, Tuple[Type[TelegramObj], dict]]: if not isinstance(obj, TelegramObject): return NotImplemented diff --git a/telegram/ext/_utils/webhookhandler.py b/telegram/ext/_utils/webhookhandler.py index 2f3dba051..b59c29fe7 100644 --- a/telegram/ext/_utils/webhookhandler.py +++ b/telegram/ext/_utils/webhookhandler.py @@ -110,12 +110,12 @@ class TelegramHandler(tornado.web.RequestHandler): """Initialize for each request - that's the interface provided by tornado""" # pylint: disable=attribute-defined-outside-init self.bot = bot - self.update_queue = update_queue - self._logger = logging.getLogger(__name__) - self.secret_token = secret_token + self.update_queue = update_queue # skipcq: PYL-W0201 + self._logger = logging.getLogger(__name__) # skipcq: PYL-W0201 + self.secret_token = secret_token # skipcq: PYL-W0201 if secret_token: self._logger.debug( - "The webhook server has a secret token, " "expecting it in incoming requests now" + "The webhook server has a secret token, expecting it in incoming requests now" ) def set_default_headers(self) -> None: diff --git a/telegram/ext/filters.py b/telegram/ext/filters.py index 5a705ee3f..ffb8ba815 100644 --- a/telegram/ext/filters.py +++ b/telegram/ext/filters.py @@ -182,8 +182,7 @@ class BaseFilter: self._name = self.__class__.__name__ if name is None else name self._data_filter = data_filter - # pylint: disable=no-self-use - def check_update(self, update: Update) -> Optional[Union[bool, DataDict]]: + def check_update(self, update: Update) -> Optional[Union[bool, DataDict]]: # skipcq: PYL-R0201 """Checks if the specified update is a message.""" if ( # Only message updates should be handled. update.channel_post