diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0aa5f1a15..0da0cea13 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.5.0' + rev: 'v0.5.6' hooks: - id: ruff name: ruff diff --git a/docs/auxil/sphinx_hooks.py b/docs/auxil/sphinx_hooks.py index 2cfbfe140..6853a7fbe 100644 --- a/docs/auxil/sphinx_hooks.py +++ b/docs/auxil/sphinx_hooks.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. import collections.abc +import contextlib import inspect import re import typing @@ -153,13 +154,11 @@ def autodoc_process_docstring( if isinstance(obj, telegram.ext.filters.BaseFilter): obj = obj.__class__ - try: + with contextlib.suppress(Exception): source_lines, start_line = inspect.getsourcelines(obj) end_line = start_line + len(source_lines) file = Path(inspect.getsourcefile(obj)).relative_to(FILE_ROOT) LINE_NUMBERS[name] = (file, start_line, end_line) - except Exception: - pass # Since we don't document the `__init__`, we call this manually to have it available for # attributes -- see the note above diff --git a/docs/auxil/tg_const_role.py b/docs/auxil/tg_const_role.py index d4d5961ad..e7d1b135b 100644 --- a/docs/auxil/tg_const_role.py +++ b/docs/auxil/tg_const_role.py @@ -88,7 +88,6 @@ class TGConstXRefRole(PyXRefRole): refnode.rawsource, CONSTANTS_ROLE, ) - return title, target except Exception as exc: sphinx_logger.exception( "%s:%d: WARNING: Did not convert reference %s due to an exception.", @@ -98,3 +97,5 @@ class TGConstXRefRole(PyXRefRole): exc_info=exc, ) return title, target + else: + return title, target diff --git a/pyproject.toml b/pyproject.toml index 551c10b1d..9285497df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,14 +128,21 @@ explicit-preview-rules = true # TODO: Drop this when RUF022 and RUF023 are out ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"] select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE", "G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "RUF022", - "RUF023", "Q", "INP", "W", "YTT", "DTZ", "ARG", "T20", "FURB"] + "RUF023", "Q", "INP", "W", "YTT", "DTZ", "ARG", "T20", "FURB", "DOC", "TRY", + "D100", "D101", "D102", "D103", "D300", "D418", "D419", "S"] # Add "A (flake8-builtins)" after we drop pylint [tool.ruff.lint.per-file-ignores] "tests/*.py" = ["B018"] -"tests/**.py" = ["RUF012", "ASYNC230", "DTZ", "ARG", "T201"] -"docs/**.py" = ["INP001", "ARG"] -"examples/**.py" = ["ARG"] +"tests/**.py" = ["RUF012", "ASYNC230", "DTZ", "ARG", "T201", "ASYNC109", "D", "S", "TRY"] +"telegram/**.py" = ["TRY003"] +"telegram/ext/_applicationbuilder.py" = ["TRY004"] +"telegram/ext/filters.py" = ["D102"] +"docs/**.py" = ["INP001", "ARG", "D", "TRY003", "S"] +"examples/**.py" = ["ARG", "D", "S105", "TRY003"] + +[tool.ruff.lint.pydocstyle] +convention = "google" # PYLINT: [tool.pylint."messages control"] diff --git a/telegram/__main__.py b/telegram/__main__.py index 2491a330a..6a508e357 100644 --- a/telegram/__main__.py +++ b/telegram/__main__.py @@ -17,7 +17,7 @@ # 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=missing-module-docstring -# ruff: noqa: T201 +# ruff: noqa: T201, D100, S603, S607 import subprocess import sys from typing import Optional diff --git a/telegram/_bot.py b/telegram/_bot.py index 5f4927cb8..d825a8878 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -324,10 +324,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): """ try: await self.initialize() - return self - except Exception as exc: + except Exception: await self.shutdown() - raise exc + raise + return self async def __aexit__( self, @@ -4271,7 +4271,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): self, offset: Optional[int] = None, limit: Optional[int] = None, - timeout: Optional[int] = None, + timeout: Optional[int] = None, # noqa: ASYNC109 allowed_updates: Optional[Sequence[str]] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, @@ -4387,7 +4387,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): self._LOGGER.critical( "Error while parsing updates! Received data was %r", result, exc_info=exc ) - raise exc + raise async def set_webhook( self, diff --git a/telegram/_telegramobject.py b/telegram/_telegramobject.py index 4f7ba92d6..6666b49b2 100644 --- a/telegram/_telegramobject.py +++ b/telegram/_telegramobject.py @@ -414,7 +414,7 @@ class TelegramObject: obj = cls(**data, api_kwargs=api_kwargs) except TypeError as exc: if "__init__() got an unexpected keyword argument" not in str(exc): - raise exc + raise if cls.__INIT_PARAMS_CHECK is not cls: signature = inspect.signature(cls) diff --git a/telegram/ext/_aioratelimiter.py b/telegram/ext/_aioratelimiter.py index 714bbc63f..3a5af9b85 100644 --- a/telegram/ext/_aioratelimiter.py +++ b/telegram/ext/_aioratelimiter.py @@ -250,7 +250,7 @@ class AIORateLimiter(BaseRateLimiter[int]): _LOGGER.exception( "Rate limit hit after maximum of %d retries", max_retries, exc_info=exc ) - raise exc + raise sleep = exc.retry_after + 0.1 _LOGGER.info("Rate limit hit. Retrying after %f seconds", sleep) diff --git a/telegram/ext/_application.py b/telegram/ext/_application.py index 670793c99..a1013ce57 100644 --- a/telegram/ext/_application.py +++ b/telegram/ext/_application.py @@ -384,10 +384,10 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica """ try: await self.initialize() - return self - except Exception as exc: + except Exception: await self.shutdown() - raise exc + raise + return self async def __aexit__( self, @@ -646,9 +646,9 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica ) _LOGGER.info("Application started") - except Exception as exc: + except Exception: self._running = False - raise exc + raise async def stop(self) -> None: """Stops the process after processing any pending updates or tasks created by @@ -1227,7 +1227,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica await self.process_error(update=update, error=exception, coroutine=coroutine) # Raise exception so that it can be set on the task and retrieved by task.exception() - raise exception + raise finally: self._mark_for_persistence_update(update=update) @@ -1445,14 +1445,16 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica 1: [CallbackQueryHandler(...), CommandHandler(...)] } + Raises: + :exc:`TypeError`: If the combination of arguments is invalid. """ if isinstance(handlers, dict) and not isinstance(group, DefaultValue): - raise ValueError("The `group` argument can only be used with a sequence of handlers.") + raise TypeError("The `group` argument can only be used with a sequence of handlers.") if isinstance(handlers, dict): for handler_group, grp_handlers in handlers.items(): if not isinstance(grp_handlers, (list, tuple)): - raise ValueError(f"Handlers for group {handler_group} must be a list or tuple") + raise TypeError(f"Handlers for group {handler_group} must be a list or tuple") for handler in grp_handlers: self.add_handler(handler, handler_group) @@ -1462,7 +1464,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica self.add_handler(handler, DefaultValue.get_value(group)) else: - raise ValueError( + raise TypeError( "The `handlers` argument must be a sequence of handlers or a " "dictionary where the keys are groups and values are sequences of handlers." ) @@ -1644,9 +1646,10 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica self.__update_persistence_event.wait(), timeout=self.persistence.update_interval, ) - return except asyncio.TimeoutError: pass + else: + return # putting this *after* the wait_for so we don't immediately update on startup as # that would make little sense diff --git a/telegram/ext/_applicationbuilder.py b/telegram/ext/_applicationbuilder.py index a54d49161..838c47495 100644 --- a/telegram/ext/_applicationbuilder.py +++ b/telegram/ext/_applicationbuilder.py @@ -207,7 +207,7 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]): self._job_queue: ODVInput[JobQueue] = DefaultValue(JobQueue()) except RuntimeError as exc: if "PTB must be installed via" not in str(exc): - raise exc + raise self._job_queue = DEFAULT_NONE self._persistence: ODVInput[BasePersistence] = DEFAULT_NONE diff --git a/telegram/ext/_baseupdateprocessor.py b/telegram/ext/_baseupdateprocessor.py index 89d51d96f..8e9af01fc 100644 --- a/telegram/ext/_baseupdateprocessor.py +++ b/telegram/ext/_baseupdateprocessor.py @@ -81,10 +81,10 @@ class BaseUpdateProcessor(AsyncContextManager["BaseUpdateProcessor"], ABC): """ try: await self.initialize() - return self - except Exception as exc: + except Exception: await self.shutdown() - raise exc + raise + return self async def __aexit__( self, diff --git a/telegram/ext/_callbackcontext.py b/telegram/ext/_callbackcontext.py index 92113bae9..ea708e0e6 100644 --- a/telegram/ext/_callbackcontext.py +++ b/telegram/ext/_callbackcontext.py @@ -272,7 +272,9 @@ class CallbackContext(Generic[BT, UD, CD, BD]): ) self.bot.callback_data_cache.drop_data(callback_query) else: - raise RuntimeError("telegram.Bot does not allow for arbitrary callback data.") + raise RuntimeError( # noqa: TRY004 + "telegram.Bot does not allow for arbitrary callback data." + ) @classmethod def from_error( diff --git a/telegram/ext/_callbackdatacache.py b/telegram/ext/_callbackdatacache.py index 150f3f055..02aebde5c 100644 --- a/telegram/ext/_callbackdatacache.py +++ b/telegram/ext/_callbackdatacache.py @@ -278,9 +278,9 @@ class CallbackDataCache: button_data = keyboard_data.button_data[button] # Update the timestamp for the LRU keyboard_data.update_access_time() - return keyboard, button_data except KeyError: return None, InvalidCallbackData(callback_data) + return keyboard, button_data @staticmethod def extract_uuids(callback_data: str) -> Tuple[str, str]: diff --git a/telegram/ext/_contexttypes.py b/telegram/ext/_contexttypes.py index ea1065112..3754ff429 100644 --- a/telegram/ext/_contexttypes.py +++ b/telegram/ext/_contexttypes.py @@ -188,7 +188,7 @@ class ContextTypes(Generic[CCT, UD, CD, BD]): user_data: Type[ADict] = dict, ): if not issubclass(context, CallbackContext): - raise ValueError("context must be a subclass of CallbackContext.") + raise TypeError("context must be a subclass of CallbackContext.") # We make all those only accessible via properties because we don't currently support # changing this at runtime, so overriding the attributes doesn't make sense diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index 4d0bef88b..d85d8822d 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -637,7 +637,7 @@ class ExtBot(Bot, Generic[RLARGS]): self, offset: Optional[int] = None, limit: Optional[int] = None, - timeout: Optional[int] = None, + timeout: Optional[int] = None, # noqa: ASYNC109 allowed_updates: Optional[Sequence[str]] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, diff --git a/telegram/ext/_updater.py b/telegram/ext/_updater.py index 04d01a83e..bdf14e0a9 100644 --- a/telegram/ext/_updater.py +++ b/telegram/ext/_updater.py @@ -145,10 +145,10 @@ class Updater(AsyncContextManager["Updater"]): """ try: await self.initialize() - return self - except Exception as exc: + except Exception: await self.shutdown() - raise exc + raise + return self async def __aexit__( self, @@ -214,7 +214,7 @@ class Updater(AsyncContextManager["Updater"]): async def start_polling( self, poll_interval: float = 0.0, - timeout: int = 10, + timeout: int = 10, # noqa: ASYNC109 bootstrap_retries: int = -1, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, @@ -339,16 +339,15 @@ class Updater(AsyncContextManager["Updater"]): _LOGGER.debug("Waiting for polling to start") await polling_ready.wait() _LOGGER.debug("Polling updates from Telegram started") - - return self.update_queue - except Exception as exc: + except Exception: self._running = False - raise exc + raise + return self.update_queue async def _start_polling( self, poll_interval: float, - timeout: int, + timeout: int, # noqa: ASYNC109 read_timeout: ODVInput[float], write_timeout: ODVInput[float], connect_timeout: ODVInput[float], @@ -384,9 +383,9 @@ class Updater(AsyncContextManager["Updater"]): pool_timeout=pool_timeout, allowed_updates=allowed_updates, ) - except TelegramError as exc: + except TelegramError: # TelegramErrors should be processed by the network retry loop - raise exc + raise except Exception as exc: # Other exceptions should not. Let's log them for now. _LOGGER.critical( @@ -446,13 +445,12 @@ class Updater(AsyncContextManager["Updater"]): pool_timeout=pool_timeout, allowed_updates=allowed_updates, ) - except TelegramError as exc: - _LOGGER.error( + except TelegramError: + _LOGGER.exception( "Error while calling `get_updates` one more time to mark all fetched updates " "as read: %s. Suppressing error to ensure graceful shutdown. When polling for " "updates is restarted, updates may be fetched again. Please adjust timeouts " "via `ApplicationBuilder` or the parameter `get_updates_request` of `Bot`.", - exc_info=exc, ) self.__polling_cleanup_cb = _get_updates_cleanup @@ -623,9 +621,9 @@ class Updater(AsyncContextManager["Updater"]): _LOGGER.debug("Waiting for webhook server to start") await webhook_ready.wait() _LOGGER.debug("Webhook server started") - except Exception as exc: + except Exception: self._running = False - raise exc + raise # Return the update queue so the main thread can insert updates return self.update_queue @@ -761,11 +759,11 @@ class Updater(AsyncContextManager["Updater"]): _LOGGER.debug("Timed out %s: %s", description, toe) # If failure is due to timeout, we should retry asap. cur_interval = 0 - except InvalidToken as pex: - _LOGGER.error("Invalid token; aborting") - raise pex + except InvalidToken: + _LOGGER.exception("Invalid token; aborting") + raise except TelegramError as telegram_exc: - _LOGGER.error("Error while %s: %s", description, telegram_exc) + _LOGGER.exception("Error while %s:", description) on_err_cb(telegram_exc) # increase waiting times on subsequent errors up to 30secs diff --git a/telegram/request/_baserequest.py b/telegram/request/_baserequest.py index d323dfb06..aa0fe232c 100644 --- a/telegram/request/_baserequest.py +++ b/telegram/request/_baserequest.py @@ -115,10 +115,10 @@ class BaseRequest( """ try: await self.initialize() - return self - except Exception as exc: + except Exception: await self.shutdown() - raise exc + raise + return self async def __aexit__( self, @@ -339,8 +339,8 @@ class BaseRequest( connect_timeout=connect_timeout, pool_timeout=pool_timeout, ) - except TelegramError as exc: - raise exc + except TelegramError: + raise except Exception as exc: raise NetworkError(f"Unknown error in HTTP implementation: {exc!r}") from exc @@ -408,7 +408,7 @@ class BaseRequest( try: return json.loads(decoded_s) except ValueError as exc: - _LOGGER.error('Can not load invalid JSON data: "%s"', decoded_s) + _LOGGER.exception('Can not load invalid JSON data: "%s"', decoded_s) raise TelegramError("Invalid server response") from exc @abc.abstractmethod diff --git a/telegram/request/_httpxrequest.py b/telegram/request/_httpxrequest.py index e98615392..3dc6cf05f 100644 --- a/telegram/request/_httpxrequest.py +++ b/telegram/request/_httpxrequest.py @@ -189,7 +189,7 @@ class HTTPXRequest(BaseRequest): self._client = self._build_client() except ImportError as exc: if "httpx[http2]" not in str(exc) and "httpx[socks]" not in str(exc): - raise exc + raise if "httpx[socks]" in str(exc): raise RuntimeError( diff --git a/tests/_files/test_animation.py b/tests/_files/test_animation.py index 74a17fca4..5e991eaba 100644 --- a/tests/_files/test_animation.py +++ b/tests/_files/test_animation.py @@ -37,7 +37,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def animation_file(): with data_file("game.gif").open("rb") as f: yield f diff --git a/tests/_files/test_audio.py b/tests/_files/test_audio.py index 12857ddc6..ced1a1d5d 100644 --- a/tests/_files/test_audio.py +++ b/tests/_files/test_audio.py @@ -37,7 +37,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def audio_file(): with data_file("telegram.mp3").open("rb") as f: yield f diff --git a/tests/_files/test_chatphoto.py b/tests/_files/test_chatphoto.py index ea853fd6b..27f3a26ba 100644 --- a/tests/_files/test_chatphoto.py +++ b/tests/_files/test_chatphoto.py @@ -36,7 +36,7 @@ from tests.auxil.networking import expect_bad_request from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def chatphoto_file(): with data_file("telegram.jpg").open("rb") as f: yield f diff --git a/tests/_files/test_document.py b/tests/_files/test_document.py index 5d078fced..913e290f9 100644 --- a/tests/_files/test_document.py +++ b/tests/_files/test_document.py @@ -37,7 +37,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def document_file(): with data_file("telegram.png").open("rb") as f: yield f diff --git a/tests/_files/test_location.py b/tests/_files/test_location.py index 5b94df491..f9a7e4c6a 100644 --- a/tests/_files/test_location.py +++ b/tests/_files/test_location.py @@ -235,7 +235,7 @@ class TestLocationWithRequest: assert protected.has_protected_content assert not unprotected.has_protected_content - @pytest.mark.xfail() + @pytest.mark.xfail async def test_send_live_location(self, bot, chat_id): message = await bot.send_location( chat_id=chat_id, diff --git a/tests/_files/test_photo.py b/tests/_files/test_photo.py index ac53a048c..1d48bba86 100644 --- a/tests/_files/test_photo.py +++ b/tests/_files/test_photo.py @@ -38,7 +38,7 @@ from tests.auxil.networking import expect_bad_request from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def photo_file(): with data_file("telegram.jpg").open("rb") as f: yield f diff --git a/tests/_files/test_sticker.py b/tests/_files/test_sticker.py index bf60272ba..a994325e1 100644 --- a/tests/_files/test_sticker.py +++ b/tests/_files/test_sticker.py @@ -49,7 +49,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def sticker_file(): with data_file("telegram.webp").open("rb") as file: yield file @@ -65,7 +65,7 @@ async def sticker(bot, chat_id): return sticker -@pytest.fixture() +@pytest.fixture def animated_sticker_file(): with data_file("telegram_animated_sticker.tgs").open("rb") as f: yield f @@ -77,7 +77,7 @@ async def animated_sticker(bot, chat_id): return (await bot.send_sticker(chat_id, sticker=f, read_timeout=50)).sticker -@pytest.fixture() +@pytest.fixture def video_sticker_file(): with data_file("telegram_video_sticker.webm").open("rb") as f: yield f @@ -524,7 +524,7 @@ class TestStickerWithRequest(TestStickerBase): await bot.send_sticker(chat_id, "") -@pytest.fixture() +@pytest.fixture async def sticker_set(bot): ss = await bot.get_sticker_set(f"test_by_{bot.username}") if len(ss.stickers) > 100: @@ -538,7 +538,7 @@ async def sticker_set(bot): return ss -@pytest.fixture() +@pytest.fixture async def animated_sticker_set(bot): ss = await bot.get_sticker_set(f"animated_test_by_{bot.username}") if len(ss.stickers) > 100: @@ -552,7 +552,7 @@ async def animated_sticker_set(bot): return ss -@pytest.fixture() +@pytest.fixture async def video_sticker_set(bot): ss = await bot.get_sticker_set(f"video_test_by_{bot.username}") if len(ss.stickers) > 100: @@ -566,7 +566,7 @@ async def video_sticker_set(bot): return ss -@pytest.fixture() +@pytest.fixture def sticker_set_thumb_file(): with data_file("sticker_set_thumb.png").open("rb") as file: yield file diff --git a/tests/_files/test_video.py b/tests/_files/test_video.py index 7f31f9f6e..29a80930f 100644 --- a/tests/_files/test_video.py +++ b/tests/_files/test_video.py @@ -37,7 +37,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def video_file(): with data_file("telegram.mp4").open("rb") as f: yield f diff --git a/tests/_files/test_videonote.py b/tests/_files/test_videonote.py index 625e85eba..5f07936ca 100644 --- a/tests/_files/test_videonote.py +++ b/tests/_files/test_videonote.py @@ -36,7 +36,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def video_note_file(): with data_file("telegram2.mp4").open("rb") as f: yield f diff --git a/tests/_files/test_voice.py b/tests/_files/test_voice.py index 8060221c7..0c92b5390 100644 --- a/tests/_files/test_voice.py +++ b/tests/_files/test_voice.py @@ -37,7 +37,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def voice_file(): with data_file("telegram.ogg").open("rb") as f: yield f diff --git a/tests/_inline/test_inlinequeryhandler.py b/tests/_inline/test_inlinequeryhandler.py index 556cea464..58431e59e 100644 --- a/tests/_inline/test_inlinequeryhandler.py +++ b/tests/_inline/test_inlinequeryhandler.py @@ -68,7 +68,7 @@ def false_update(request): return Update(update_id=2, **request.param) -@pytest.fixture() +@pytest.fixture def inline_query(bot): update = Update( 0, diff --git a/tests/conftest.py b/tests/conftest.py index a9ef3e686..dd553f9fe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -124,7 +124,7 @@ async def bot(bot_info): yield _bot -@pytest.fixture() +@pytest.fixture def one_time_bot(bot_info): """A function scoped bot since the session bot would shutdown when `async with app` finishes""" return make_bot(bot_info) @@ -206,7 +206,7 @@ def provider_token(bot_info): return bot_info["payment_provider_token"] -@pytest.fixture() +@pytest.fixture async def app(bot_info): # We build a new bot each time so that we use `app` in a context manager without problems application = ( @@ -218,7 +218,7 @@ async def app(bot_info): await application.shutdown() -@pytest.fixture() +@pytest.fixture async def updater(bot_info): # We build a new bot each time so that we use `updater` in a context manager without problems up = Updater(bot=make_bot(bot_info), update_queue=asyncio.Queue()) @@ -228,7 +228,7 @@ async def updater(bot_info): await up.shutdown() -@pytest.fixture() +@pytest.fixture def thumb_file(): with data_file("thumb.jpg").open("rb") as f: yield f @@ -291,6 +291,6 @@ def timezone(tzinfo): return tzinfo -@pytest.fixture() +@pytest.fixture def tmp_file(tmp_path) -> Path: return tmp_path / uuid4().hex diff --git a/tests/ext/_utils/test_trackingdict.py b/tests/ext/_utils/test_trackingdict.py index 5ddf3d371..5fa21467e 100644 --- a/tests/ext/_utils/test_trackingdict.py +++ b/tests/ext/_utils/test_trackingdict.py @@ -23,14 +23,14 @@ from telegram.ext._utils.trackingdict import TrackingDict from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def td() -> TrackingDict: td = TrackingDict() td.update_no_track({1: 1}) return td -@pytest.fixture() +@pytest.fixture def data() -> dict: return {1: 1} diff --git a/tests/ext/test_application.py b/tests/ext/test_application.py index a74f3c739..c423c5d5f 100644 --- a/tests/ext/test_application.py +++ b/tests/ext/test_application.py @@ -639,11 +639,11 @@ class TestApplication: assert len(app.handlers[-1]) == 1 # Now lets test the errors which can be produced- - with pytest.raises(ValueError, match="The `group` argument"): + with pytest.raises(TypeError, match="The `group` argument"): app.add_handlers({2: [msg_handler_set_count]}, group=0) - with pytest.raises(ValueError, match="Handlers for group 3"): + with pytest.raises(TypeError, match="Handlers for group 3"): app.add_handlers({3: msg_handler_set_count}) - with pytest.raises(ValueError, match="The `handlers` argument must be a sequence"): + with pytest.raises(TypeError, match="The `handlers` argument must be a sequence"): app.add_handlers({msg_handler_set_count}) await app.stop() diff --git a/tests/ext/test_applicationbuilder.py b/tests/ext/test_applicationbuilder.py index 9fcbc1401..189164d1b 100644 --- a/tests/ext/test_applicationbuilder.py +++ b/tests/ext/test_applicationbuilder.py @@ -48,7 +48,7 @@ from tests.auxil.files import data_file from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def builder(): return ApplicationBuilder() diff --git a/tests/ext/test_basepersistence.py b/tests/ext/test_basepersistence.py index fb61e79bb..d3c2ef771 100644 --- a/tests/ext/test_basepersistence.py +++ b/tests/ext/test_basepersistence.py @@ -261,7 +261,7 @@ def build_conversation_handler(name: str, persistent: bool = True) -> BaseHandle return TrackingConversationHandler(name=name, persistent=persistent) -@pytest.fixture() +@pytest.fixture def papp(request, bot_info) -> Application: papp_input = request.param store_data = {} diff --git a/tests/ext/test_baseupdateprocessor.py b/tests/ext/test_baseupdateprocessor.py index de36ea4aa..c30e6417c 100644 --- a/tests/ext/test_baseupdateprocessor.py +++ b/tests/ext/test_baseupdateprocessor.py @@ -28,7 +28,7 @@ from tests.auxil.asyncio_helpers import call_after from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def mock_processor(): class MockProcessor(SimpleUpdateProcessor): test_flag = False diff --git a/tests/ext/test_businessconnectionhandler.py b/tests/ext/test_businessconnectionhandler.py index c8d741332..c64c059dc 100644 --- a/tests/ext/test_businessconnectionhandler.py +++ b/tests/ext/test_businessconnectionhandler.py @@ -88,7 +88,7 @@ def business_connection(bot): return bc -@pytest.fixture() +@pytest.fixture def business_connection_update(bot, business_connection): return Update(0, business_connection=business_connection) diff --git a/tests/ext/test_businessmessagesdeletedhandler.py b/tests/ext/test_businessmessagesdeletedhandler.py index a15a0a0c2..f377c9482 100644 --- a/tests/ext/test_businessmessagesdeletedhandler.py +++ b/tests/ext/test_businessmessagesdeletedhandler.py @@ -85,7 +85,7 @@ def business_messages_deleted(bot): return bmd -@pytest.fixture() +@pytest.fixture def business_messages_deleted_update(bot, business_messages_deleted): return Update(0, deleted_business_messages=business_messages_deleted) diff --git a/tests/ext/test_callbackdatacache.py b/tests/ext/test_callbackdatacache.py index be7fbace0..2082e8091 100644 --- a/tests/ext/test_callbackdatacache.py +++ b/tests/ext/test_callbackdatacache.py @@ -31,7 +31,7 @@ from tests.auxil.envvars import TEST_WITH_OPT_DEPS from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def callback_data_cache(bot): return CallbackDataCache(bot) diff --git a/tests/ext/test_callbackqueryhandler.py b/tests/ext/test_callbackqueryhandler.py index f96c074d2..c1dccd8df 100644 --- a/tests/ext/test_callbackqueryhandler.py +++ b/tests/ext/test_callbackqueryhandler.py @@ -65,7 +65,7 @@ def false_update(request): return Update(update_id=2, **request.param) -@pytest.fixture() +@pytest.fixture def callback_query(bot): update = Update(0, callback_query=CallbackQuery(2, User(1, "", False), None, data="test data")) update._unfreeze() diff --git a/tests/ext/test_chatjoinrequesthandler.py b/tests/ext/test_chatjoinrequesthandler.py index 3d2e38f44..9b769e07e 100644 --- a/tests/ext/test_chatjoinrequesthandler.py +++ b/tests/ext/test_chatjoinrequesthandler.py @@ -96,7 +96,7 @@ def chat_join_request(time, bot): return cjr -@pytest.fixture() +@pytest.fixture def chat_join_request_update(bot, chat_join_request): return Update(0, chat_join_request=chat_join_request) diff --git a/tests/ext/test_chatmemberhandler.py b/tests/ext/test_chatmemberhandler.py index ada95288c..9f4705b59 100644 --- a/tests/ext/test_chatmemberhandler.py +++ b/tests/ext/test_chatmemberhandler.py @@ -81,7 +81,7 @@ def chat_member_updated(): ) -@pytest.fixture() +@pytest.fixture def chat_member(bot, chat_member_updated): update = Update(0, my_chat_member=chat_member_updated) update._unfreeze() diff --git a/tests/ext/test_contexttypes.py b/tests/ext/test_contexttypes.py index afe73bb21..c1d488076 100644 --- a/tests/ext/test_contexttypes.py +++ b/tests/ext/test_contexttypes.py @@ -40,7 +40,7 @@ class TestContextTypes: assert ct.chat_data is float assert ct.user_data is bool - with pytest.raises(ValueError, match="subclass of CallbackContext"): + with pytest.raises(TypeError, match="subclass of CallbackContext"): ContextTypes(context=bool) def test_data_assignment(self): diff --git a/tests/ext/test_dictpersistence.py b/tests/ext/test_dictpersistence.py index ecd004858..0b725826c 100644 --- a/tests/ext/test_dictpersistence.py +++ b/tests/ext/test_dictpersistence.py @@ -31,27 +31,27 @@ def _reset_callback_data_cache(cdc_bot): cdc_bot.callback_data_cache.clear_callback_queries() -@pytest.fixture() +@pytest.fixture def bot_data(): return {"test1": "test2", "test3": {"test4": "test5"}} -@pytest.fixture() +@pytest.fixture def chat_data(): return {-12345: {"test1": "test2", "test3": {"test4": "test5"}}, -67890: {3: "test4"}} -@pytest.fixture() +@pytest.fixture def user_data(): return {12345: {"test1": "test2", "test3": {"test4": "test5"}}, 67890: {3: "test4"}} -@pytest.fixture() +@pytest.fixture def callback_data(): return [("test1", 1000, {"button1": "test0", "button2": "test1"})], {"test1": "test2"} -@pytest.fixture() +@pytest.fixture def conversations(): return { "name1": {(123, 123): 3, (456, 654): 4}, @@ -60,27 +60,27 @@ def conversations(): } -@pytest.fixture() +@pytest.fixture def user_data_json(user_data): return json.dumps(user_data) -@pytest.fixture() +@pytest.fixture def chat_data_json(chat_data): return json.dumps(chat_data) -@pytest.fixture() +@pytest.fixture def bot_data_json(bot_data): return json.dumps(bot_data) -@pytest.fixture() +@pytest.fixture def callback_data_json(callback_data): return json.dumps(callback_data) -@pytest.fixture() +@pytest.fixture def conversations_json(conversations): return """{"name1": {"[123, 123]": 3, "[456, 654]": 4}, "name2": {"[123, 321]": 1, "[890, 890]": 2}, "name3": diff --git a/tests/ext/test_filters.py b/tests/ext/test_filters.py index 9cf47dc47..76b8dec91 100644 --- a/tests/ext/test_filters.py +++ b/tests/ext/test_filters.py @@ -43,7 +43,7 @@ from telegram.ext import filters from tests.auxil.slots import mro_slots -@pytest.fixture() +@pytest.fixture def update(): update = Update( 0, diff --git a/tests/ext/test_jobqueue.py b/tests/ext/test_jobqueue.py index 929591d38..436dabbcc 100644 --- a/tests/ext/test_jobqueue.py +++ b/tests/ext/test_jobqueue.py @@ -44,7 +44,7 @@ class CustomContext(CallbackContext): pass -@pytest.fixture() +@pytest.fixture async def job_queue(app): jq = JobQueue() jq.set_application(app) diff --git a/tests/ext/test_messagereactionhandler.py b/tests/ext/test_messagereactionhandler.py index 8f4172c9e..3a71b20e7 100644 --- a/tests/ext/test_messagereactionhandler.py +++ b/tests/ext/test_messagereactionhandler.py @@ -112,12 +112,12 @@ def message_reaction_count_updated(time, bot): return mr -@pytest.fixture() +@pytest.fixture def message_reaction_update(bot, message_reaction_updated): return Update(0, message_reaction=message_reaction_updated) -@pytest.fixture() +@pytest.fixture def message_reaction_count_update(bot, message_reaction_count_updated): return Update(0, message_reaction_count=message_reaction_count_updated) diff --git a/tests/ext/test_picklepersistence.py b/tests/ext/test_picklepersistence.py index 86a26eeb3..ef23715b5 100644 --- a/tests/ext/test_picklepersistence.py +++ b/tests/ext/test_picklepersistence.py @@ -50,27 +50,27 @@ def _reset_callback_data_cache(cdc_bot): cdc_bot.callback_data_cache.clear_callback_queries() -@pytest.fixture() +@pytest.fixture def bot_data(): return {"test1": "test2", "test3": {"test4": "test5"}} -@pytest.fixture() +@pytest.fixture def chat_data(): return {-12345: {"test1": "test2", "test3": {"test4": "test5"}}, -67890: {3: "test4"}} -@pytest.fixture() +@pytest.fixture def user_data(): return {12345: {"test1": "test2", "test3": {"test4": "test5"}}, 67890: {3: "test4"}} -@pytest.fixture() +@pytest.fixture def callback_data(): return [("test1", 1000, {"button1": "test0", "button2": "test1"})], {"test1": "test2"} -@pytest.fixture() +@pytest.fixture def conversations(): return { "name1": {(123, 123): 3, (456, 654): 4}, @@ -79,7 +79,7 @@ def conversations(): } -@pytest.fixture() +@pytest.fixture def pickle_persistence(): return PicklePersistence( filepath="pickletest", @@ -88,7 +88,7 @@ def pickle_persistence(): ) -@pytest.fixture() +@pytest.fixture def pickle_persistence_only_bot(): return PicklePersistence( filepath="pickletest", @@ -98,7 +98,7 @@ def pickle_persistence_only_bot(): ) -@pytest.fixture() +@pytest.fixture def pickle_persistence_only_chat(): return PicklePersistence( filepath="pickletest", @@ -108,7 +108,7 @@ def pickle_persistence_only_chat(): ) -@pytest.fixture() +@pytest.fixture def pickle_persistence_only_user(): return PicklePersistence( filepath="pickletest", @@ -118,7 +118,7 @@ def pickle_persistence_only_user(): ) -@pytest.fixture() +@pytest.fixture def pickle_persistence_only_callback(): return PicklePersistence( filepath="pickletest", @@ -128,7 +128,7 @@ def pickle_persistence_only_callback(): ) -@pytest.fixture() +@pytest.fixture def bad_pickle_files(): for name in [ "pickletest_user_data", @@ -142,7 +142,7 @@ def bad_pickle_files(): return True -@pytest.fixture() +@pytest.fixture def invalid_pickle_files(): for name in [ "pickletest_user_data", @@ -159,7 +159,7 @@ def invalid_pickle_files(): return True -@pytest.fixture() +@pytest.fixture def good_pickle_files(user_data, chat_data, bot_data, callback_data, conversations): data = { "user_data": user_data, @@ -183,7 +183,7 @@ def good_pickle_files(user_data, chat_data, bot_data, callback_data, conversatio return True -@pytest.fixture() +@pytest.fixture def pickle_files_wo_bot_data(user_data, chat_data, callback_data, conversations): data = { "user_data": user_data, @@ -204,7 +204,7 @@ def pickle_files_wo_bot_data(user_data, chat_data, callback_data, conversations) return True -@pytest.fixture() +@pytest.fixture def pickle_files_wo_callback_data(user_data, chat_data, bot_data, conversations): data = { "user_data": user_data, @@ -225,7 +225,7 @@ def pickle_files_wo_callback_data(user_data, chat_data, bot_data, conversations) return True -@pytest.fixture() +@pytest.fixture def update(bot): user = User(id=321, first_name="test_user", is_bot=False) chat = Chat(id=123, type="group") diff --git a/tests/ext/test_pollanswerhandler.py b/tests/ext/test_pollanswerhandler.py index d36b38d22..d86b90ff1 100644 --- a/tests/ext/test_pollanswerhandler.py +++ b/tests/ext/test_pollanswerhandler.py @@ -67,7 +67,7 @@ def false_update(request): return Update(update_id=2, **request.param) -@pytest.fixture() +@pytest.fixture def poll_answer(bot): return Update(0, poll_answer=PollAnswer(1, [0, 1], User(2, "test user", False), Chat(1, ""))) diff --git a/tests/ext/test_prefixhandler.py b/tests/ext/test_prefixhandler.py index a42ec4e05..f858e0052 100644 --- a/tests/ext/test_prefixhandler.py +++ b/tests/ext/test_prefixhandler.py @@ -56,15 +56,15 @@ class TestPrefixHandler(BaseTest): def commands(self, request): return TestPrefixHandler.COMMANDS[: request.param] - @pytest.fixture() + @pytest.fixture def prefix_message_text(self, prefix, command): return prefix + command - @pytest.fixture() + @pytest.fixture def prefix_message(self, prefix_message_text): return make_message(prefix_message_text) - @pytest.fixture() + @pytest.fixture def prefix_message_update(self, prefix_message): return make_message_update(prefix_message) diff --git a/tests/ext/test_updater.py b/tests/ext/test_updater.py index 1fd8985de..f72161008 100644 --- a/tests/ext/test_updater.py +++ b/tests/ext/test_updater.py @@ -86,7 +86,7 @@ class TestUpdater: # This is needed instead of pytest's temp_path because the file path gets too long on macOS # otherwise - @pytest.fixture() + @pytest.fixture def file_path(self) -> str: path = TEST_DATA_PATH / "test.sock" yield str(path) @@ -571,7 +571,7 @@ class TestUpdater: else: assert len(caplog.records) > 0 assert any( - "Error while getting Updates: TestMessage" in record.getMessage() + "Error while getting Updates:" in record.getMessage() and record.name == "telegram.ext.Updater" for record in caplog.records ) @@ -593,7 +593,7 @@ class TestUpdater: else: assert len(caplog.records) > 0 assert any( - "Error while getting Updates: TestMessage" in record.getMessage() + "Error while getting Updates:" in record.getMessage() and record.name == "telegram.ext.Updater" for record in caplog.records ) diff --git a/tests/request/test_request.py b/tests/request/test_request.py index 9ce5ee286..6adcdf7c0 100644 --- a/tests/request/test_request.py +++ b/tests/request/test_request.py @@ -74,7 +74,7 @@ def mocker_factory( return make_assertion -@pytest.fixture() +@pytest.fixture async def httpx_request(): async with NonchalantHttpxRequest() as rq: yield rq diff --git a/tests/test_bot.py b/tests/test_bot.py index e34763592..cdf00082d 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -107,7 +107,7 @@ from ._files.test_photo import photo_file from .auxil.build_messages import make_message -@pytest.fixture() +@pytest.fixture async def message(bot, chat_id): # mostly used in tests for edit_message out = await bot.send_message( chat_id, "Text", disable_web_page_preview=True, disable_notification=True diff --git a/tests/test_chatbackground.py b/tests/test_chatbackground.py index 1f8be1eb4..900fc5870 100644 --- a/tests/test_chatbackground.py +++ b/tests/test_chatbackground.py @@ -146,7 +146,7 @@ def iter_args( yield inst_at, json_at -@pytest.fixture() +@pytest.fixture def background_type(request): return request.param() @@ -254,7 +254,7 @@ class TestBackgroundTypeWithoutRequest: assert hash(f) != hash(c) -@pytest.fixture() +@pytest.fixture def background_fill(request): return request.param() diff --git a/tests/test_chatboost.py b/tests/test_chatboost.py index bc33e1fe2..f0ef14361 100644 --- a/tests/test_chatboost.py +++ b/tests/test_chatboost.py @@ -107,7 +107,7 @@ def user_chat_boosts(chat_boost): ) -@pytest.fixture() +@pytest.fixture def chat_boost_source(request): return request.param() diff --git a/tests/test_chatmember.py b/tests/test_chatmember.py index 28293a6cc..b4eac51cf 100644 --- a/tests/test_chatmember.py +++ b/tests/test_chatmember.py @@ -181,7 +181,7 @@ def iter_args(instance: ChatMember, de_json_inst: ChatMember, include_optional: yield inst_at, json_at -@pytest.fixture() +@pytest.fixture def chat_member_type(request): return request.param() diff --git a/tests/test_forum.py b/tests/test_forum.py index 55419a385..1f143616e 100644 --- a/tests/test_forum.py +++ b/tests/test_forum.py @@ -56,7 +56,7 @@ async def forum_topic_object(forum_group_id, emoji_id): ) -@pytest.fixture() +@pytest.fixture async def real_topic(bot, emoji_id, forum_group_id): result = await bot.create_forum_topic( chat_id=forum_group_id, diff --git a/tests/test_messageorigin.py b/tests/test_messageorigin.py index 1e46fc53c..10d9fa778 100644 --- a/tests/test_messageorigin.py +++ b/tests/test_messageorigin.py @@ -114,7 +114,7 @@ def iter_args( yield inst_at, json_at -@pytest.fixture() +@pytest.fixture def message_origin_type(request): return request.param() diff --git a/tests/test_pollhandler.py b/tests/test_pollhandler.py index 52b0675e1..a87c45b28 100644 --- a/tests/test_pollhandler.py +++ b/tests/test_pollhandler.py @@ -68,7 +68,7 @@ def false_update(request): return Update(update_id=2, **request.param) -@pytest.fixture() +@pytest.fixture def poll(bot): return Update( 0, diff --git a/tests/test_reaction.py b/tests/test_reaction.py index 30e287ca5..6f3d3cb46 100644 --- a/tests/test_reaction.py +++ b/tests/test_reaction.py @@ -89,7 +89,7 @@ def iter_args(instance: ReactionType, de_json_inst: ReactionType, include_option yield inst_at, json_at -@pytest.fixture() +@pytest.fixture def reaction_type(request): return request.param() diff --git a/tests/test_stars.py b/tests/test_stars.py index fb1339a72..d3560af7d 100644 --- a/tests/test_stars.py +++ b/tests/test_stars.py @@ -49,12 +49,12 @@ def withdrawal_state_succeeded(): ) -@pytest.fixture() +@pytest.fixture def withdrawal_state_failed(): return RevenueWithdrawalStateFailed() -@pytest.fixture() +@pytest.fixture def withdrawal_state_pending(): return RevenueWithdrawalStatePending() @@ -65,7 +65,7 @@ def transaction_partner_user(): ) -@pytest.fixture() +@pytest.fixture def transaction_partner_other(): return TransactionPartnerOther() @@ -86,7 +86,7 @@ def star_transaction(): ) -@pytest.fixture() +@pytest.fixture def star_transactions(): return StarTransactions( transactions=[ diff --git a/tests/test_user.py b/tests/test_user.py index ca5ea2011..8b0ae5df5 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -47,7 +47,7 @@ def json_dict(): } -@pytest.fixture() +@pytest.fixture def user(bot): user = User( id=TestUserBase.id_,