Skip to content
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
6 changes: 6 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
# and we document the types anyway
autodoc_typehints = "none"

# Show docstring for special members
autodoc_default_options = {
"special-members": True,
"exclude-members": "__init__",
}

# Fail on warnings & unresolved references etc
nitpicky = True

Expand Down
2 changes: 2 additions & 0 deletions docs/substitutions/global.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@
.. |removed_thumb_url_note| replace:: Removed the deprecated argument and attribute ``thumb_url``.

.. |removed_thumb_wildcard_note| replace:: Removed the deprecated arguments and attributes ``thumb_*``.

.. |async_context_manager| replace:: Asynchronous context manager which
13 changes: 13 additions & 0 deletions telegram/_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
finally:
await bot.shutdown()

.. seealso:: :meth:`__aenter__` and :meth:`__aexit__`.

Note:
* Most bot methods have the argument ``api_kwargs`` which allows passing arbitrary keywords
to the Telegram API. This can be used to access new features of the API before they are
Expand Down Expand Up @@ -310,6 +312,16 @@ def __init__(
self._freeze()

async def __aenter__(self: BT) -> BT:
"""
|async_context_manager| :meth:`initializes <initialize>` the Bot.

Returns:
The initialized Bot instance.

Raises:
:exc:`Exception`: If an exception is raised during initialization, :meth:`shutdown`
is called in this case.
"""
try:
await self.initialize()
return self
Expand All @@ -323,6 +335,7 @@ async def __aexit__(
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
"""|async_context_manager| :meth:`shuts down <shutdown>` the Bot."""
# Make sure not to return `True` so that exceptions are not suppressed
# https://docs.python.org/3/reference/datamodel.html?#object.__aexit__
await self.shutdown()
Expand Down
14 changes: 12 additions & 2 deletions telegram/ext/_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
finally:
await application.shutdown()

.. seealso:: :meth:`__aenter__` and :meth:`__aexit__`.

Examples:
:any:`Echo Bot <examples.echobot>`

Expand Down Expand Up @@ -345,7 +347,15 @@ def __init__(
self.__create_task_tasks: Set[asyncio.Task] = set() # Used for awaiting tasks upon exit

async def __aenter__(self: _AppType) -> _AppType: # noqa: PYI019
"""Simple context manager which initializes the App."""
"""|async_context_manager| :meth:`initializes <initialize>` the App.

Returns:
The initialized App instance.

Raises:
:exc:`Exception`: If an exception is raised during initialization, :meth:`shutdown`
is called in this case.
"""
try:
await self.initialize()
return self
Expand All @@ -359,7 +369,7 @@ async def __aexit__(
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
"""Shutdown the App from the context manager."""
"""|async_context_manager| :meth:`shuts down <shutdown>` the App."""
# Make sure not to return `True` so that exceptions are not suppressed
# https://docs.python.org/3/reference/datamodel.html?#object.__aexit__
await self.shutdown()
Expand Down
31 changes: 29 additions & 2 deletions telegram/ext/_baseupdateprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ class BaseUpdateProcessor(ABC):
"""An abstract base class for update processors. You can use this class to implement
your own update processor.

Instances of this class can be used as asyncio context managers, where

.. code:: python

async with processor:
# code

is roughly equivalent to

.. code:: python

try:
await processor.initialize()
# code
finally:
await processor.shutdown()

.. seealso:: :meth:`__aenter__` and :meth:`__aexit__`.

.. seealso:: :wiki:`Concurrency`

.. versionadded:: 20.4
Expand All @@ -49,7 +68,15 @@ def __init__(self, max_concurrent_updates: int):
self._semaphore = BoundedSemaphore(self.max_concurrent_updates)

async def __aenter__(self) -> "BaseUpdateProcessor":
"""Simple context manager which initializes the Processor."""
"""|async_context_manager| :meth:`initializes <initialize>` the Processor.

Returns:
The initialized Processor instance.

Raises:
:exc:`Exception`: If an exception is raised during initialization, :meth:`shutdown`
is called in this case.
"""
try:
await self.initialize()
return self
Expand All @@ -63,7 +90,7 @@ async def __aexit__(
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
"""Simple context manager which shuts down the Processor."""
"""|async_context_manager| :meth:`shuts down <shutdown>` the Processor."""
await self.shutdown()

@property
Expand Down
15 changes: 13 additions & 2 deletions telegram/ext/_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class Updater(AsyncContextManager["Updater"]):
finally:
await updater.shutdown()

.. seealso:: :meth:`__aenter__` and :meth:`__aexit__`.

.. seealso:: :wiki:`Architecture Overview <Architecture>`,
:wiki:`Builder Pattern <Builder-Pattern>`

Expand Down Expand Up @@ -126,7 +128,16 @@ def __init__(
self.__polling_cleanup_cb: Optional[Callable[[], Coroutine[Any, Any, None]]] = None

async def __aenter__(self: _UpdaterType) -> _UpdaterType: # noqa: PYI019
"""Simple context manager which initializes the Updater."""
"""
|async_context_manager| :meth:`initializes <initialize>` the Updater.

Returns:
The initialized Updater instance.

Raises:
:exc:`Exception`: If an exception is raised during initialization, :meth:`shutdown`
is called in this case.
"""
try:
await self.initialize()
return self
Expand All @@ -140,7 +151,7 @@ async def __aexit__(
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
"""Shutdown the Updater from the context manager."""
"""|async_context_manager| :meth:`shuts down <shutdown>` the Updater."""
# Make sure not to return `True` so that exceptions are not suppressed
# https://docs.python.org/3/reference/datamodel.html?#object.__aexit__
await self.shutdown()
Expand Down
12 changes: 12 additions & 0 deletions telegram/request/_baserequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class BaseRequest(
finally:
await request_object.shutdown()

.. seealso:: :meth:`__aenter__` and :meth:`__aexit__`.

Tip:
JSON encoding and decoding is done with the standard library's :mod:`json` by default.
To use a custom library for this, you can override :meth:`parse_json_payload` and implement
Expand Down Expand Up @@ -99,6 +101,15 @@ class BaseRequest(
"""

async def __aenter__(self: RT) -> RT:
"""|async_context_manager| :meth:`initializes <initialize>` the Request.

Returns:
The initialized Request instance.

Raises:
:exc:`Exception`: If an exception is raised during initialization, :meth:`shutdown`
is called in this case.
"""
try:
await self.initialize()
return self
Expand All @@ -112,6 +123,7 @@ async def __aexit__(
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
"""|async_context_manager| :meth:`shuts down <shutdown>` the Request."""
# Make sure not to return `True` so that exceptions are not suppressed
# https://docs.python.org/3/reference/datamodel.html?#object.__aexit__
await self.shutdown()
Expand Down