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

warning to install optional dependencies #3393

Merged
merged 11 commits into from Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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: 3 additions & 0 deletions docs/source/examples.rst
Expand Up @@ -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`
-------------------------------
Expand Down Expand Up @@ -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`
--------------------------
Expand Down Expand Up @@ -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
--------
Expand Down
4 changes: 4 additions & 0 deletions examples/arbitrarycallbackdatabot.py
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions examples/passportbot.py
Expand Up @@ -10,6 +10,9 @@
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
Expand Down
4 changes: 4 additions & 0 deletions examples/timerbot.py
Expand Up @@ -16,6 +16,10 @@
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
Expand Down
32 changes: 23 additions & 9 deletions telegram/ext/_application.py
Expand Up @@ -64,7 +64,7 @@

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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -264,7 +262,6 @@ def __init__(

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]] = {}
Expand Down Expand Up @@ -306,6 +303,7 @@ def __init__(
# 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()
Expand Down Expand Up @@ -337,6 +335,22 @@ def concurrent_updates(self) -> int:
"""
return self._concurrent_updates

@property
def job_queue(self) -> Optional["JobQueue"]:
"""
:class:`telegram.ext.JobQueue`: The :class:`JobQueue` used by the
clot27 marked this conversation as resolved.
Show resolved Hide resolved
: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]`."
)
return self._job_queue

async def initialize(self) -> None:
"""Initializes the Application by initializing:

Expand Down Expand Up @@ -511,8 +525,8 @@ async def start(self) -> None:
)
_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(
Expand Down Expand Up @@ -561,9 +575,9 @@ async def stop(self) -> None:
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")
Expand Down
6 changes: 6 additions & 0 deletions telegram/ext/_callbackcontext.py
Expand Up @@ -21,6 +21,7 @@

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

Expand Down Expand Up @@ -389,6 +390,11 @@ def job_queue(self) -> Optional["JobQueue"]:
.. seealso:: `Job Queue <https://github.com/python-telegram-bot/
python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue>`_
"""
if self._application.job_queue is None:
warn(
"No `JobQueue` set up. To use `JobQueue`, you must install PTB via "
"`pip install python-telegram-bot[job_queue]`."
)
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved
return self._application.job_queue

@property
Expand Down
15 changes: 14 additions & 1 deletion tests/test_application.py
Expand Up @@ -201,6 +201,18 @@ async def post_shutdown(application: Application) -> None:
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]`."
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved
)
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"
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved

def test_custom_context_init(self, bot):
cc = ContextTypes(
context=CustomContext,
Expand Down Expand Up @@ -385,6 +397,7 @@ def test_builder(self, app):
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:
Expand Down Expand Up @@ -1945,4 +1958,4 @@ async def abort_app():
if platform.system() == "Windows":
assert received_signals == []
else:
assert received_signals == [signal.SIGINT, signal.SIGTERM, signal.SIGABRT]
assert received_signals == [signal.SIGINT, signal.SIGTERM, signal.SIGABRT]
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 3 additions & 2 deletions tests/test_applicationbuilder.py
Expand Up @@ -51,7 +51,7 @@ def builder():
@pytest.mark.skipif(TEST_WITH_OPT_DEPS, reason="Optional dependencies are installed")
class TestApplicationBuilderNoOptDeps:
def test_init(self, builder):
builder.token("token")
builder.token("token").job_queue(None)
app = builder.build()
assert app.job_queue is None

Expand Down Expand Up @@ -416,9 +416,10 @@ def test_no_updater(self, bot, builder):
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
assert app.job_queue is None
assert isinstance(app.update_queue, asyncio.Queue)
assert isinstance(app.updater, Updater)
assert isinstance(app.updater, Updater)
17 changes: 16 additions & 1 deletion tests/test_callbackcontext.py
Expand Up @@ -38,7 +38,7 @@


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}'"
Expand All @@ -58,6 +58,21 @@ def test_from_job(self, app):
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
Bibo-Joshi marked this conversation as resolved.
Show resolved Hide resolved
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))
Expand Down
4 changes: 2 additions & 2 deletions tests/test_conversationhandler.py
Expand Up @@ -1000,7 +1000,7 @@ async def test_no_running_job_queue_warning(self, app, bot, user1, recwarn, jq):
# 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)
app.add_handler(handler)

message = Message(
Expand Down Expand Up @@ -1031,7 +1031,7 @@ def mocked_run_once(*a, **kw):
class DictJB(JobQueue):
pass

app.job_queue = DictJB()
app = ApplicationBuilder().token(bot.token).job_queue(DictJB())
monkeypatch.setattr(app.job_queue, "run_once", mocked_run_once)
handler = ConversationHandler(
entry_points=self.entry_points,
Expand Down