mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-12-22 14:35:00 +01:00
Add Notes and Warnings About Optional Dependencies (#3393)
This commit is contained in:
parent
4123e7aa57
commit
f8be97c12c
11 changed files with 88 additions and 21 deletions
|
@ -40,6 +40,7 @@ up a job to send a message to that user after 30 seconds. The user can
|
|||
also cancel the timer by sending ``/unset``. To learn more about the
|
||||
``JobQueue``, read `this wiki
|
||||
article <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue>`__.
|
||||
Note: To use ``JobQueue``, you must install PTB via ``pip install python-telegram-bot[job-queue]``
|
||||
|
||||
:any:`examples.conversationbot`
|
||||
-------------------------------
|
||||
|
@ -115,6 +116,7 @@ Don’t forget to enable and configure payments with
|
|||
`@BotFather <https://telegram.me/BotFather>`_. Check out this
|
||||
`guide <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Telegram-Passport>`__
|
||||
on Telegram passports in PTB.
|
||||
Note: To use Telegram Passport, you must install PTB via ``pip install python-telegram-bot[passport]``
|
||||
|
||||
:any:`examples.paymentbot`
|
||||
--------------------------
|
||||
|
@ -162,6 +164,7 @@ combination with ``telegram.ext.Application``.
|
|||
|
||||
This example showcases how PTBs “arbitrary callback data” feature can be
|
||||
used.
|
||||
Note: To use arbitrary callback data, you must install PTB via ``pip install python-telegram-bot[callback-data]``
|
||||
|
||||
Pure API
|
||||
--------
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
For detailed info on arbitrary callback data, see the wiki page at
|
||||
https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data
|
||||
|
||||
Note:
|
||||
To use arbitrary callback data, you must install PTB via
|
||||
`pip install python-telegram-bot[callback-data]`
|
||||
"""
|
||||
import logging
|
||||
from typing import List, Tuple, cast
|
||||
|
|
|
@ -10,6 +10,9 @@ See https://telegram.org/blog/passport for info about what telegram passport is.
|
|||
See https://github.com/python-telegram-bot/python-telegram-bot/wiki/Telegram-Passport
|
||||
for how to use Telegram Passport properly with python-telegram-bot.
|
||||
|
||||
Note:
|
||||
To use Telegram Passport, you must install PTB via
|
||||
`pip install python-telegram-bot[passport]`
|
||||
"""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
|
|
@ -16,6 +16,10 @@ Usage:
|
|||
Basic Alarm Bot example, sends a message after a set time.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
|
||||
Note:
|
||||
To use arbitrary callback data, you must install ptb via
|
||||
`pip install python-telegram-bot[callback-data]`
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
|
|
@ -64,7 +64,7 @@ from telegram.ext._utils.types import BD, BT, CCT, CD, JQ, UD, ConversationKey,
|
|||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Message
|
||||
from telegram.ext import ConversationHandler
|
||||
from telegram.ext import ConversationHandler, JobQueue
|
||||
from telegram.ext._applicationbuilder import InitApplicationBuilder
|
||||
from telegram.ext._jobqueue import Job
|
||||
|
||||
|
@ -151,8 +151,6 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
update_queue (:class:`asyncio.Queue`): The synchronized queue that will contain the
|
||||
updates.
|
||||
updater (:class:`telegram.ext.Updater`): Optional. The updater used by this application.
|
||||
job_queue (:class:`telegram.ext.JobQueue`): Optional. The :class:`telegram.ext.JobQueue`
|
||||
instance to pass onto handler callbacks.
|
||||
chat_data (:obj:`types.MappingProxyType`): A dictionary handlers can use to store data for
|
||||
the chat. For each integer chat id, the corresponding value of this mapping is
|
||||
available as :attr:`telegram.ext.CallbackContext.chat_data` in handler callbacks for
|
||||
|
@ -218,6 +216,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
"_concurrent_updates_sem",
|
||||
"_conversation_handler_conversations",
|
||||
"_initialized",
|
||||
"_job_queue",
|
||||
"_running",
|
||||
"_user_data",
|
||||
"_user_ids_to_be_deleted_in_persistence",
|
||||
|
@ -228,7 +227,6 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
"context_types",
|
||||
"error_handlers",
|
||||
"handlers",
|
||||
"job_queue",
|
||||
"persistence",
|
||||
"post_init",
|
||||
"post_shutdown",
|
||||
|
@ -264,7 +262,6 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
|
||||
self.bot = bot
|
||||
self.update_queue = update_queue
|
||||
self.job_queue = job_queue
|
||||
self.context_types = context_types
|
||||
self.updater = updater
|
||||
self.handlers: Dict[int, List[BaseHandler]] = {}
|
||||
|
@ -306,6 +303,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
# A number of low-level helpers for the internal logic
|
||||
self._initialized = False
|
||||
self._running = False
|
||||
self._job_queue = job_queue
|
||||
self.__update_fetcher_task: Optional[asyncio.Task] = None
|
||||
self.__update_persistence_task: Optional[asyncio.Task] = None
|
||||
self.__update_persistence_event = asyncio.Event()
|
||||
|
@ -337,6 +335,23 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
"""
|
||||
return self._concurrent_updates
|
||||
|
||||
@property
|
||||
def job_queue(self) -> Optional["JobQueue"]:
|
||||
"""
|
||||
:class:`telegram.ext.JobQueue`: The :class:`JobQueue` used by the
|
||||
:class:`telegram.ext.Application`.
|
||||
|
||||
.. seealso:: `Job Queue <https://github.com/python-telegram-bot/
|
||||
python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue>`_
|
||||
"""
|
||||
if self._job_queue is None:
|
||||
warn(
|
||||
"No `JobQueue` set up. To use `JobQueue`, you must install PTB via "
|
||||
"`pip install python-telegram-bot[job_queue]`.",
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._job_queue
|
||||
|
||||
async def initialize(self) -> None:
|
||||
"""Initializes the Application by initializing:
|
||||
|
||||
|
@ -511,8 +526,8 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
)
|
||||
_logger.debug("Loop for updating persistence started")
|
||||
|
||||
if self.job_queue:
|
||||
await self.job_queue.start() # type: ignore[union-attr]
|
||||
if self._job_queue:
|
||||
await self._job_queue.start() # type: ignore[union-attr]
|
||||
_logger.debug("JobQueue started")
|
||||
|
||||
self.__update_fetcher_task = asyncio.create_task(
|
||||
|
@ -561,9 +576,9 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AbstractAsyncContextManager)
|
|||
await self.__update_fetcher_task
|
||||
_logger.debug("Application stopped fetching of updates.")
|
||||
|
||||
if self.job_queue:
|
||||
if self._job_queue:
|
||||
_logger.debug("Waiting for running jobs to finish")
|
||||
await self.job_queue.stop(wait=True) # type: ignore[union-attr]
|
||||
await self._job_queue.stop(wait=True) # type: ignore[union-attr]
|
||||
_logger.debug("JobQueue stopped")
|
||||
|
||||
_logger.debug("Waiting for `create_task` calls to be processed")
|
||||
|
|
|
@ -21,6 +21,7 @@ from typing import TYPE_CHECKING, Coroutine, Dict, Generic, List, Match, NoRetur
|
|||
|
||||
from telegram._callbackquery import CallbackQuery
|
||||
from telegram._update import Update
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.ext._extbot import ExtBot
|
||||
from telegram.ext._utils.types import BD, BT, CD, UD
|
||||
|
||||
|
@ -389,7 +390,13 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
|
|||
.. seealso:: `Job Queue <https://github.com/python-telegram-bot/
|
||||
python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue>`_
|
||||
"""
|
||||
return self._application.job_queue
|
||||
if self._application._job_queue is None: # pylint: disable=protected-access
|
||||
warn(
|
||||
"No `JobQueue` set up. To use `JobQueue`, you must install PTB via "
|
||||
"`pip install python-telegram-bot[job_queue]`.",
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._application._job_queue # pylint: disable=protected-access
|
||||
|
||||
@property
|
||||
def update_queue(self) -> "Queue[object]":
|
||||
|
|
|
@ -676,7 +676,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
|
|||
try:
|
||||
# both job_queue & conversation_timeout are checked before calling _schedule_job
|
||||
j_queue = application.job_queue
|
||||
self.timeout_jobs[conversation_key] = j_queue.run_once(
|
||||
self.timeout_jobs[conversation_key] = j_queue.run_once( # type: ignore[union-attr]
|
||||
self._trigger_timeout,
|
||||
self.conversation_timeout, # type: ignore[arg-type]
|
||||
data=_ConversationTimeoutContext(conversation_key, update, application, context),
|
||||
|
|
|
@ -201,6 +201,18 @@ class TestApplication:
|
|||
post_shutdown=None,
|
||||
)
|
||||
|
||||
def test_job_queue(self, bot, app, recwarn):
|
||||
expected_warning = (
|
||||
"No `JobQueue` set up. To use `JobQueue`, you must install PTB via "
|
||||
"`pip install python-telegram-bot[job_queue]`."
|
||||
)
|
||||
assert app.job_queue is app._job_queue
|
||||
application = ApplicationBuilder().token(bot.token).job_queue(None).build()
|
||||
assert application.job_queue is None
|
||||
assert len(recwarn) == 1
|
||||
assert str(recwarn[0].message) == expected_warning
|
||||
assert recwarn[0].filename == __file__, "wrong stacklevel"
|
||||
|
||||
def test_custom_context_init(self, bot):
|
||||
cc = ContextTypes(
|
||||
context=CustomContext,
|
||||
|
@ -385,6 +397,7 @@ class TestApplication:
|
|||
builder_2.token(app.bot.token)
|
||||
|
||||
@pytest.mark.parametrize("job_queue", (True, False))
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
async def test_start_stop_processing_updates(self, bot, job_queue):
|
||||
# TODO: repeat a similar test for create_task, persistence processing and job queue
|
||||
if job_queue:
|
||||
|
|
|
@ -50,6 +50,7 @@ def builder():
|
|||
|
||||
@pytest.mark.skipif(TEST_WITH_OPT_DEPS, reason="Optional dependencies are installed")
|
||||
class TestApplicationBuilderNoOptDeps:
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
def test_init(self, builder):
|
||||
builder.token("token")
|
||||
app = builder.build()
|
||||
|
@ -416,6 +417,7 @@ class TestApplicationBuilder:
|
|||
assert isinstance(app.job_queue, JobQueue)
|
||||
assert app.job_queue.application is app
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
def test_no_job_queue(self, bot, builder):
|
||||
app = builder.token(bot.token).job_queue(None).build()
|
||||
assert app.bot.token == bot.token
|
||||
|
|
|
@ -38,7 +38,7 @@ CallbackContext.refresh_data is tested in TestBasePersistence
|
|||
|
||||
|
||||
class TestCallbackContext:
|
||||
def test_slot_behaviour(self, app, mro_slots, recwarn):
|
||||
def test_slot_behaviour(self, app, mro_slots):
|
||||
c = CallbackContext(app)
|
||||
for attr in c.__slots__:
|
||||
assert getattr(c, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
|
@ -58,6 +58,21 @@ class TestCallbackContext:
|
|||
assert callback_context.job_queue is app.job_queue
|
||||
assert callback_context.update_queue is app.update_queue
|
||||
|
||||
def test_job_queue(self, bot, app, recwarn):
|
||||
expected_warning = (
|
||||
"No `JobQueue` set up. To use `JobQueue`, you must install PTB via "
|
||||
"`pip install python-telegram-bot[job_queue]`."
|
||||
)
|
||||
|
||||
callback_context = CallbackContext(app)
|
||||
assert callback_context.job_queue is app.job_queue
|
||||
app = ApplicationBuilder().job_queue(None).token(bot.token).build()
|
||||
callback_context = CallbackContext(app)
|
||||
assert callback_context.job_queue is None
|
||||
assert len(recwarn) == 1
|
||||
assert str(recwarn[0].message) == expected_warning
|
||||
assert recwarn[0].filename == __file__, "wrong stacklevel"
|
||||
|
||||
def test_from_update(self, app):
|
||||
update = Update(
|
||||
0, message=Message(0, None, Chat(1, "chat"), from_user=User(1, "user", False))
|
||||
|
|
|
@ -996,11 +996,8 @@ class TestConversationHandler:
|
|||
fallbacks=self.fallbacks,
|
||||
conversation_timeout=0.5,
|
||||
)
|
||||
# save app.job_queue in temp variable jqueue
|
||||
# and then set app.job_queue to None.
|
||||
jqueue = app.job_queue
|
||||
if not jq:
|
||||
app.job_queue = None
|
||||
app = ApplicationBuilder().token(bot.token).job_queue(None).build()
|
||||
app.add_handler(handler)
|
||||
|
||||
message = Message(
|
||||
|
@ -1018,11 +1015,15 @@ class TestConversationHandler:
|
|||
async with app:
|
||||
await app.process_update(Update(update_id=0, message=message))
|
||||
await asyncio.sleep(0.5)
|
||||
assert len(recwarn) == 1
|
||||
assert str(recwarn[0].message).startswith("Ignoring `conversation_timeout`")
|
||||
assert ("is not running" if jq else "has no JobQueue.") in str(recwarn[0].message)
|
||||
if jq:
|
||||
assert len(recwarn) == 1
|
||||
else:
|
||||
assert len(recwarn) == 2
|
||||
assert str(recwarn[0].message if jq else recwarn[1].message).startswith(
|
||||
"Ignoring `conversation_timeout`"
|
||||
)
|
||||
assert ("is not running" if jq else "No `JobQueue` set up.") in str(recwarn[0].message)
|
||||
# now set app.job_queue back to it's original value
|
||||
app.job_queue = jqueue
|
||||
|
||||
async def test_schedule_job_exception(self, app, bot, user1, monkeypatch, caplog):
|
||||
def mocked_run_once(*a, **kw):
|
||||
|
@ -1031,7 +1032,7 @@ class TestConversationHandler:
|
|||
class DictJB(JobQueue):
|
||||
pass
|
||||
|
||||
app.job_queue = DictJB()
|
||||
app = ApplicationBuilder().token(bot.token).job_queue(DictJB()).build()
|
||||
monkeypatch.setattr(app.job_queue, "run_once", mocked_run_once)
|
||||
handler = ConversationHandler(
|
||||
entry_points=self.entry_points,
|
||||
|
|
Loading…
Reference in a new issue