Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Improve Type Completeness #4466

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

Merged
merged 19 commits into from
Sep 14, 2024
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
33 changes: 33 additions & 0 deletions .github/workflows/type_completeness_monthly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Check Type Completeness Monthly Run
on:
schedule:
# Run first friday of the month at 03:17 - odd time to spread load on GitHub Actions
- cron: '17 3 1-7 * 5'

jobs:
test-type-completeness:
name: test-type-completeness
runs-on: ubuntu-latest
steps:
- uses: Bibo-Joshi/[email protected]
id: pyright-type-completeness
with:
package-name: telegram
python-version: 3.12
pyright-version: ~=1.1.367
- name: Check Output
uses: jannekem/run-python-script-action@v1
env:
TYPE_COMPLETENESS: ${{ steps.pyright-type-completeness.outputs.base-completeness-score }}
with:
script: |
import os
completeness = float(os.getenv("TYPE_COMPLETENESS"))

if completeness >= 1:
exit(0)

text = f"Type Completeness Decreased to {completeness}. ❌"
error(text)
set_summary(text)
exit(1)
4 changes: 2 additions & 2 deletions examples/nestedconversationbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,8 @@ def main() -> None:
entry_points=[CommandHandler("start", start)],
states={
SHOWING: [CallbackQueryHandler(start, pattern="^" + str(END) + "$")],
SELECTING_ACTION: selection_handlers,
SELECTING_LEVEL: selection_handlers,
SELECTING_ACTION: selection_handlers, # type: ignore[dict-item]
SELECTING_LEVEL: selection_handlers, # type: ignore[dict-item]
DESCRIBING_SELF: [description_conv],
STOPPING: [CommandHandler("start", start)],
},
Expand Down
12 changes: 7 additions & 5 deletions telegram/ext/_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def __init__(
self.update_queue: asyncio.Queue[object] = update_queue
self.context_types: ContextTypes[CCT, UD, CD, BD] = context_types
self.updater: Optional[Updater] = updater
self.handlers: Dict[int, List[BaseHandler[Any, CCT]]] = {}
self.handlers: Dict[int, List[BaseHandler[Any, CCT, Any]]] = {}
self.error_handlers: Dict[
HandlerCallback[object, CCT, None], Union[bool, DefaultValue[bool]]
] = {}
Expand Down Expand Up @@ -1352,7 +1352,7 @@ async def process_update(self, update: object) -> None:
# (in __create_task_callback)
self._mark_for_persistence_update(update=update)

def add_handler(self, handler: BaseHandler[Any, CCT], group: int = DEFAULT_GROUP) -> None:
def add_handler(self, handler: BaseHandler[Any, CCT, Any], group: int = DEFAULT_GROUP) -> None:
"""Register a handler.

TL;DR: Order and priority counts. 0 or 1 handlers per group will be used. End handling of
Expand Down Expand Up @@ -1420,8 +1420,8 @@ def add_handler(self, handler: BaseHandler[Any, CCT], group: int = DEFAULT_GROUP
def add_handlers(
self,
handlers: Union[
Union[List[BaseHandler[Any, CCT]], Tuple[BaseHandler[Any, CCT]]],
Dict[int, Union[List[BaseHandler[Any, CCT]], Tuple[BaseHandler[Any, CCT]]]],
Union[List[BaseHandler[Any, CCT, Any]], Tuple[BaseHandler[Any, CCT, Any]]],
Dict[int, Union[List[BaseHandler[Any, CCT, Any]], Tuple[BaseHandler[Any, CCT, Any]]]],
],
group: Union[int, DefaultValue[int]] = _DEFAULT_0,
) -> None:
Expand Down Expand Up @@ -1469,7 +1469,9 @@ def add_handlers(
"dictionary where the keys are groups and values are sequences of handlers."
)

def remove_handler(self, handler: BaseHandler[Any, CCT], group: int = DEFAULT_GROUP) -> None:
def remove_handler(
self, handler: BaseHandler[Any, CCT, Any], group: int = DEFAULT_GROUP
) -> None:
"""Remove a handler from the specified group.

Args:
Expand Down
16 changes: 10 additions & 6 deletions telegram/ext/_callbackcontext.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
NoReturn,
Optional,
Type,
TypeVar,
Union,
)

Expand All @@ -49,6 +50,9 @@
"/wiki/Storing-bot%2C-user-and-chat-related-data"
)

# something like poor mans "typing.Self" for py<3.11
ST = TypeVar("ST", bound="CallbackContext[Any, Any, Any, Any]")


class CallbackContext(Generic[BT, UD, CD, BD]):
"""
Expand Down Expand Up @@ -133,24 +137,24 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
)

def __init__(
self: "CCT",
application: "Application[BT, CCT, UD, CD, BD, Any]",
self: ST,
application: "Application[BT, ST, UD, CD, BD, Any]",
chat_id: Optional[int] = None,
user_id: Optional[int] = None,
):
self._application: Application[BT, CCT, UD, CD, BD, Any] = application
self._application: Application[BT, ST, UD, CD, BD, Any] = application
self._chat_id: Optional[int] = chat_id
self._user_id: Optional[int] = user_id
self.args: Optional[List[str]] = None
self.matches: Optional[List[Match[str]]] = None
self.error: Optional[Exception] = None
self.job: Optional[Job[CCT]] = None
self.job: Optional[Job[Any]] = None
self.coroutine: Optional[
Union[Generator[Optional[Future[object]], None, Any], Awaitable[Any]]
] = None

@property
def application(self) -> "Application[BT, CCT, UD, CD, BD, Any]":
def application(self) -> "Application[BT, ST, UD, CD, BD, Any]":
""":class:`telegram.ext.Application`: The application associated with this context."""
return self._application

Expand Down Expand Up @@ -398,7 +402,7 @@ def bot(self) -> BT:
return self._application.bot

@property
def job_queue(self) -> Optional["JobQueue[CCT]"]:
def job_queue(self) -> Optional["JobQueue[ST]"]:
"""
:class:`telegram.ext.JobQueue`: The :class:`JobQueue` used by the
:class:`telegram.ext.Application`.
Expand Down
7 changes: 4 additions & 3 deletions telegram/ext/_handlers/basehandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@
UT = TypeVar("UT")


class BaseHandler(Generic[UT, CCT], ABC):
class BaseHandler(Generic[UT, CCT, RT], ABC):
"""The base class for all update handlers. Create custom handlers by inheriting from it.

Warning:
When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.

This class is a :class:`~typing.Generic` class and accepts two type variables:
This class is a :class:`~typing.Generic` class and accepts three type variables:

1. The type of the updates that this handler will handle. Must coincide with the type of the
first argument of :paramref:`callback`. :meth:`check_update` must only accept
Expand All @@ -54,6 +54,7 @@ class BaseHandler(Generic[UT, CCT], ABC):
For this type variable, one should usually provide a :class:`~typing.TypeVar` that is
also used for the mentioned method arguments. That way, a type checker can check whether
this handler fits the definition of the :class:`~Application`.
3. The return type of the :paramref:`callback` function accepted by this handler.

.. seealso:: :wiki:`Types of Handlers <Types-of-Handlers>`

Expand Down Expand Up @@ -89,7 +90,7 @@ async def callback(update: Update, context: CallbackContext)
)

def __init__(
self,
self: "BaseHandler[UT, CCT, RT]",
callback: HandlerCallback[UT, CCT, RT],
block: DVType[bool] = DEFAULT_TRUE,
):
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/businessconnectionhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
RT = TypeVar("RT")


class BusinessConnectionHandler(BaseHandler[Update, CCT]):
class BusinessConnectionHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram
:attr:`Business Connections <telegram.Update.business_connection>`.

Expand Down Expand Up @@ -65,7 +65,7 @@ async def callback(update: Update, context: CallbackContext)
)

def __init__(
self,
self: "BusinessConnectionHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
user_id: Optional[SCT[int]] = None,
username: Optional[SCT[str]] = None,
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/businessmessagesdeletedhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
RT = TypeVar("RT")


class BusinessMessagesDeletedHandler(BaseHandler[Update, CCT]):
class BusinessMessagesDeletedHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle
:attr:`deleted Telegram Business messages <telegram.Update.deleted_business_messages>`.

Expand Down Expand Up @@ -65,7 +65,7 @@ async def callback(update: Update, context: CallbackContext)
)

def __init__(
self,
self: "BusinessMessagesDeletedHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
chat_id: Optional[SCT[int]] = None,
username: Optional[SCT[str]] = None,
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/callbackqueryhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
RT = TypeVar("RT")


class CallbackQueryHandler(BaseHandler[Update, CCT]):
class CallbackQueryHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram
:attr:`callback queries <telegram.Update.callback_query>`. Optionally based on a regex.

Expand Down Expand Up @@ -125,7 +125,7 @@ async def callback(update: Update, context: CallbackContext)
__slots__ = ("game_pattern", "pattern")

def __init__(
self,
self: "CallbackQueryHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
pattern: Optional[
Union[str, Pattern[str], type, Callable[[object], Optional[bool]]]
Expand Down
8 changes: 4 additions & 4 deletions telegram/ext/_handlers/chatboosthandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
from telegram import Update
from telegram.ext._handlers.basehandler import BaseHandler
from telegram.ext._utils._update_parsing import parse_chat_id, parse_username
from telegram.ext._utils.types import CCT, HandlerCallback
from telegram.ext._utils.types import CCT, RT, HandlerCallback


class ChatBoostHandler(BaseHandler[Update, CCT]):
class ChatBoostHandler(BaseHandler[Update, CCT, RT]):
"""
Handler class to handle Telegram updates that contain a chat boost.

Expand Down Expand Up @@ -84,8 +84,8 @@ async def callback(update: Update, context: CallbackContext)
and :attr:`telegram.Update.removed_chat_boost`."""

def __init__(
self,
callback: HandlerCallback[Update, CCT, None],
self: "ChatBoostHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
chat_boost_types: int = CHAT_BOOST,
chat_id: Optional[int] = None,
chat_username: Optional[str] = None,
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/chatjoinrequesthandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from telegram.ext._utils.types import CCT, HandlerCallback


class ChatJoinRequestHandler(BaseHandler[Update, CCT]):
class ChatJoinRequestHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram updates that contain
:attr:`telegram.Update.chat_join_request`.

Expand Down Expand Up @@ -81,7 +81,7 @@ async def callback(update: Update, context: CallbackContext)
)

def __init__(
self,
self: "ChatJoinRequestHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
chat_id: Optional[SCT[int]] = None,
username: Optional[SCT[str]] = None,
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/chatmemberhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
RT = TypeVar("RT")


class ChatMemberHandler(BaseHandler[Update, CCT]):
class ChatMemberHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram updates that contain a chat member update.

Warning:
Expand Down Expand Up @@ -87,7 +87,7 @@ async def callback(update: Update, context: CallbackContext)
and :attr:`telegram.Update.chat_member`."""

def __init__(
self,
self: "ChatMemberHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
chat_member_types: int = MY_CHAT_MEMBER,
block: DVType[bool] = DEFAULT_TRUE,
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/choseninlineresulthandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from telegram.ext import Application


class ChosenInlineResultHandler(BaseHandler[Update, CCT]):
class ChosenInlineResultHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram updates that contain
:attr:`telegram.Update.chosen_inline_result`.

Expand Down Expand Up @@ -76,7 +76,7 @@ async def callback(update: Update, context: CallbackContext)
__slots__ = ("pattern",)

def __init__(
self,
self: "ChosenInlineResultHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
block: DVType[bool] = DEFAULT_TRUE,
pattern: Optional[Union[str, Pattern[str]]] = None,
Expand Down
4 changes: 2 additions & 2 deletions telegram/ext/_handlers/commandhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
RT = TypeVar("RT")


class CommandHandler(BaseHandler[Update, CCT]):
class CommandHandler(BaseHandler[Update, CCT, RT]):
"""Handler class to handle Telegram commands.

Commands are Telegram messages that start with ``/``, optionally followed by an ``@`` and the
Expand Down Expand Up @@ -118,7 +118,7 @@ async def callback(update: Update, context: CallbackContext)
__slots__ = ("commands", "filters", "has_args")

def __init__(
self,
self: "CommandHandler[CCT, RT]",
command: SCT[str],
callback: HandlerCallback[Update, CCT, RT],
filters: Optional[filters_module.BaseFilter] = None,
Expand Down
Loading
Loading