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

Add Python 3.12 beta to test matrix #3751

Merged
merged 26 commits into from Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c7ea5fd
Remove Python 3.7 from testing, docs and packaging
Bibo-Joshi Jun 2, 2023
f1784b5
Re-add note on CI bots
Bibo-Joshi Jun 3, 2023
03d3c33
temporarily run tests on this branch
harshil21 Jun 3, 2023
4de4643
Add missing new line
Bibo-Joshi Jun 4, 2023
457e4ef
Adopt Py3.8+ features: `missing_ok` Parameter (#3742)
Trifase Jun 4, 2023
a1c2fe7
Introduce Walrus Operator (#3749)
thefunkycat Jun 8, 2023
f663f37
Add python 3.12 to test matrix
harshil21 Jun 9, 2023
b49d03f
correct typo
harshil21 Jun 9, 2023
9d3345c
Remove Python 3.7 Workaround for `PicklePersistence` (#3740)
harshil21 Jun 9, 2023
1a3e4f7
Fix tests on py 3.12
harshil21 Jun 9, 2023
8c86a34
Merge branch 'master' into drop-py-37
Bibo-Joshi Jun 12, 2023
cf71a38
Drop `CancelledError` (#3754)
clot27 Jun 17, 2023
9181369
Make use of `@final`, `Final` and `Literal` (#3753)
Bibo-Joshi Jun 17, 2023
27a8683
fix error with `Literal`, causing tests/docs to fail (#3764)
lemontree210 Jun 19, 2023
b44e4af
Review: don't drop support for async gens for py < 3.12
harshil21 Jun 20, 2023
40c2cf3
Merge branch 'drop-py-37' into add-py-312
harshil21 Jun 20, 2023
8234f3c
Bump mypy and address review
harshil21 Jun 20, 2023
162004f
Review: Add deprecation warning & modify type hints
harshil21 Jul 2, 2023
8b73410
use 3.12 beta 3
harshil21 Jul 2, 2023
4962c48
merge master and fix conflicts
harshil21 Jul 2, 2023
9d0c980
try to fix type completeness CI check
harshil21 Jul 2, 2023
e753dd7
fix a leftover merge conflict
harshil21 Jul 2, 2023
0755fe1
bump mypy again
harshil21 Jul 2, 2023
316e500
try bumping pyright
harshil21 Jul 2, 2023
69ef58b
review: fix pyright by applying 'RT' generic
harshil21 Jul 4, 2023
816f020
Merge branch 'master' into add-py-312
Bibo-Joshi Jul 4, 2023
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
5 changes: 3 additions & 2 deletions .github/workflows/test.yml
Expand Up @@ -3,6 +3,7 @@ on:
pull_request:
branches:
- master
- drop-py-37
push:
branches:
- master
Expand All @@ -16,7 +17,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12.0-beta.2']
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: False
steps:
Expand Down Expand Up @@ -88,7 +89,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: [3.7]
python-version: [3.11]
os: [ubuntu-latest]
fail-fast: False
steps:
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Expand Up @@ -35,7 +35,7 @@ repos:
- aiolimiter~=1.1.0
- . # this basically does `pip install -e .`
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.3.0
rev: v1.4.0
hooks:
- id: mypy
name: mypy-ptb
Expand Down Expand Up @@ -67,7 +67,7 @@ repos:
- id: pyupgrade
files: ^(telegram|examples|tests|docs)/.*\.py$
args:
- --py37-plus
- --py38-plus
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
Expand Down
1 change: 1 addition & 0 deletions AUTHORS.rst
Expand Up @@ -24,6 +24,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Abshar <https://github.com/abxhr>`_
- `Alateas <https://github.com/alateas>`_
- `Ales Dokshanin <https://github.com/alesdokshanin>`_
- `Alizia <https://github.com/thefunkycat>`_
- `Ambro17 <https://github.com/Ambro17>`_
- `Andrej Zhilenkov <https://github.com/Andrej730>`_
- `Anton Tagunov <https://github.com/anton-tagunov>`_
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -77,7 +77,7 @@ Introduction

This library provides a pure Python, asynchronous interface for the
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
It's compatible with Python versions **3.7+**.
It's compatible with Python versions **3.8+**.

In addition to the pure API implementation, this library features a number of high-level classes to
make the development of bots easy and straightforward. These classes are contained in the
Expand Down
2 changes: 1 addition & 1 deletion README_RAW.rst
Expand Up @@ -77,7 +77,7 @@ Introduction

This library provides a pure Python, asynchronous interface for the
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
It's compatible with Python versions **3.7+**.
It's compatible with Python versions **3.8+**.

``python-telegram-bot-raw`` is part of the `python-telegram-bot <https://python-telegram-bot.org>`_ ecosystem and provides the pure API functionality extracted from PTB. It therefore does not have independent release schedules, changelogs or documentation.

Expand Down
9 changes: 6 additions & 3 deletions docs/auxil/admonition_inserter.py
Expand Up @@ -174,8 +174,7 @@ def _create_available_in(self) -> dict[type, str]:
break

for line in lines_with_attrs:
line_match = attr_docstr_pattern.match(line)
if not line_match:
if not (line_match := attr_docstr_pattern.match(line)):
continue

target_attr = line_match.group("attr_name")
Expand Down Expand Up @@ -529,7 +528,11 @@ def _resolve_arg(self, arg: Any) -> Iterator[Union[type, None]]:
# For custom generics like telegram.ext._application.Application[~BT, ~CCT, ~UD...].
# This must come before the check for isinstance(type) because GenericAlias can also be
# recognized as type if it belongs to <class 'types.GenericAlias'>.
elif str(type(arg)) in ("<class 'typing._GenericAlias'>", "<class 'types.GenericAlias'>"):
elif str(type(arg)) in (
"<class 'typing._GenericAlias'>",
"<class 'types.GenericAlias'>",
"<class 'typing._LiteralGenericAlias'>",
):
if "telegram" in str(arg):
# get_origin() of telegram.ext._application.Application[~BT, ~CCT, ~UD...]
# will produce <class 'telegram.ext._application.Application'>
Expand Down
6 changes: 4 additions & 2 deletions docs/auxil/sphinx_hooks.py
Expand Up @@ -189,8 +189,10 @@ def autodoc_process_bases(app, name, obj, option, bases: list):
bases[idx] = f":class:`{base}`"

# Now convert `telegram._message.Message` to `telegram.Message` etc
match = re.search(pattern=r"(telegram(\.ext|))\.[_\w\.]+", string=base)
if not match or "_utils" in base:
if (
not (match := re.search(pattern=r"(telegram(\.ext|))\.[_\w\.]+", string=base))
or "_utils" in base
):
continue

parts = match.group(0).split(".")
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
@@ -1,14 +1,14 @@
[tool.black]
line-length = 99
target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
target-version = ['py38', 'py39', 'py310', 'py311']

[tool.isort] # black config
profile = "black"
line_length = 99

[tool.ruff]
line-length = 99
target-version = "py37"
target-version = "py38"
show-fixes = true
ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915"]
select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
Expand Down
3 changes: 1 addition & 2 deletions setup.py
Expand Up @@ -105,13 +105,12 @@ def get_setup_kwargs(raw=False):
"Topic :: Internet",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
python_requires=">=3.7",
python_requires=">=3.8",
)

return kwargs
Expand Down
10 changes: 5 additions & 5 deletions telegram/_botcommand.py
Expand Up @@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Bot Command."""

from typing import ClassVar, Optional
from typing import Final, Optional

from telegram import constants
from telegram._telegramobject import TelegramObject
Expand Down Expand Up @@ -61,22 +61,22 @@ def __init__(self, command: str, description: str, *, api_kwargs: Optional[JSOND

self._freeze()

MIN_COMMAND: ClassVar[int] = constants.BotCommandLimit.MIN_COMMAND
MIN_COMMAND: Final[int] = constants.BotCommandLimit.MIN_COMMAND
""":const:`telegram.constants.BotCommandLimit.MIN_COMMAND`

.. versionadded:: 20.0
"""
MAX_COMMAND: ClassVar[int] = constants.BotCommandLimit.MAX_COMMAND
MAX_COMMAND: Final[int] = constants.BotCommandLimit.MAX_COMMAND
""":const:`telegram.constants.BotCommandLimit.MAX_COMMAND`

.. versionadded:: 20.0
"""
MIN_DESCRIPTION: ClassVar[int] = constants.BotCommandLimit.MIN_DESCRIPTION
MIN_DESCRIPTION: Final[int] = constants.BotCommandLimit.MIN_DESCRIPTION
""":const:`telegram.constants.BotCommandLimit.MIN_DESCRIPTION`

.. versionadded:: 20.0
"""
MAX_DESCRIPTION: ClassVar[int] = constants.BotCommandLimit.MAX_DESCRIPTION
MAX_DESCRIPTION: Final[int] = constants.BotCommandLimit.MAX_DESCRIPTION
""":const:`telegram.constants.BotCommandLimit.MAX_DESCRIPTION`

.. versionadded:: 20.0
Expand Down
16 changes: 8 additions & 8 deletions telegram/_botcommandscope.py
Expand Up @@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=redefined-builtin
"""This module contains objects representing Telegram bot command scopes."""
from typing import TYPE_CHECKING, ClassVar, Dict, Optional, Type, Union
from typing import TYPE_CHECKING, Dict, Final, Optional, Type, Union

from telegram import constants
from telegram._telegramobject import TelegramObject
Expand Down Expand Up @@ -60,19 +60,19 @@ class BotCommandScope(TelegramObject):

__slots__ = ("type",)

DEFAULT: ClassVar[str] = constants.BotCommandScopeType.DEFAULT
DEFAULT: Final[str] = constants.BotCommandScopeType.DEFAULT
""":const:`telegram.constants.BotCommandScopeType.DEFAULT`"""
ALL_PRIVATE_CHATS: ClassVar[str] = constants.BotCommandScopeType.ALL_PRIVATE_CHATS
ALL_PRIVATE_CHATS: Final[str] = constants.BotCommandScopeType.ALL_PRIVATE_CHATS
""":const:`telegram.constants.BotCommandScopeType.ALL_PRIVATE_CHATS`"""
ALL_GROUP_CHATS: ClassVar[str] = constants.BotCommandScopeType.ALL_GROUP_CHATS
ALL_GROUP_CHATS: Final[str] = constants.BotCommandScopeType.ALL_GROUP_CHATS
""":const:`telegram.constants.BotCommandScopeType.ALL_GROUP_CHATS`"""
ALL_CHAT_ADMINISTRATORS: ClassVar[str] = constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS
ALL_CHAT_ADMINISTRATORS: Final[str] = constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS
""":const:`telegram.constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS`"""
CHAT: ClassVar[str] = constants.BotCommandScopeType.CHAT
CHAT: Final[str] = constants.BotCommandScopeType.CHAT
""":const:`telegram.constants.BotCommandScopeType.CHAT`"""
CHAT_ADMINISTRATORS: ClassVar[str] = constants.BotCommandScopeType.CHAT_ADMINISTRATORS
CHAT_ADMINISTRATORS: Final[str] = constants.BotCommandScopeType.CHAT_ADMINISTRATORS
""":const:`telegram.constants.BotCommandScopeType.CHAT_ADMINISTRATORS`"""
CHAT_MEMBER: ClassVar[str] = constants.BotCommandScopeType.CHAT_MEMBER
CHAT_MEMBER: Final[str] = constants.BotCommandScopeType.CHAT_MEMBER
""":const:`telegram.constants.BotCommandScopeType.CHAT_MEMBER`"""

def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None):
Expand Down
4 changes: 2 additions & 2 deletions telegram/_botname.py
Expand Up @@ -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/].
"""This module contains an object that represent a Telegram bots name."""
from typing import ClassVar, Optional
from typing import Final, Optional

from telegram import constants
from telegram._telegramobject import TelegramObject
Expand Down Expand Up @@ -50,5 +50,5 @@ def __init__(self, name: str, *, api_kwargs: Optional[JSONDict] = None):

self._freeze()

MAX_LENGTH: ClassVar[int] = constants.BotNameLimit.MAX_NAME_LENGTH
MAX_LENGTH: Final[int] = constants.BotNameLimit.MAX_NAME_LENGTH
""":const:`telegram.constants.BotNameLimit.MAX_NAME_LENGTH`"""
4 changes: 2 additions & 2 deletions telegram/_callbackquery.py
Expand Up @@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=redefined-builtin
"""This module contains an object that represents a Telegram CallbackQuery"""
from typing import TYPE_CHECKING, ClassVar, Optional, Sequence, Tuple, Union
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union

from telegram import constants
from telegram._files.location import Location
Expand Down Expand Up @@ -771,7 +771,7 @@ async def copy_message(
message_thread_id=message_thread_id,
)

MAX_ANSWER_TEXT_LENGTH: ClassVar[
MAX_ANSWER_TEXT_LENGTH: Final[
int
] = constants.CallbackQueryLimit.ANSWER_CALLBACK_QUERY_TEXT_LENGTH
"""
Expand Down
12 changes: 6 additions & 6 deletions telegram/_chat.py
Expand Up @@ -20,7 +20,7 @@
"""This module contains an object that represents a Telegram Chat."""
from datetime import datetime
from html import escape
from typing import TYPE_CHECKING, ClassVar, Optional, Sequence, Tuple, Union
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union

from telegram import constants
from telegram._chatlocation import ChatLocation
Expand Down Expand Up @@ -303,18 +303,18 @@ class Chat(TelegramObject):
"has_aggressive_anti_spam_enabled",
)

SENDER: ClassVar[str] = constants.ChatType.SENDER
SENDER: Final[str] = constants.ChatType.SENDER
""":const:`telegram.constants.ChatType.SENDER`

.. versionadded:: 13.5
"""
PRIVATE: ClassVar[str] = constants.ChatType.PRIVATE
PRIVATE: Final[str] = constants.ChatType.PRIVATE
""":const:`telegram.constants.ChatType.PRIVATE`"""
GROUP: ClassVar[str] = constants.ChatType.GROUP
GROUP: Final[str] = constants.ChatType.GROUP
""":const:`telegram.constants.ChatType.GROUP`"""
SUPERGROUP: ClassVar[str] = constants.ChatType.SUPERGROUP
SUPERGROUP: Final[str] = constants.ChatType.SUPERGROUP
""":const:`telegram.constants.ChatType.SUPERGROUP`"""
CHANNEL: ClassVar[str] = constants.ChatType.CHANNEL
CHANNEL: Final[str] = constants.ChatType.CHANNEL
""":const:`telegram.constants.ChatType.CHANNEL`"""

def __init__(
Expand Down
6 changes: 3 additions & 3 deletions telegram/_chatlocation.py
Expand Up @@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a location to which a chat is connected."""

from typing import TYPE_CHECKING, ClassVar, Optional
from typing import TYPE_CHECKING, Final, Optional

from telegram import constants
from telegram._files.location import Location
Expand Down Expand Up @@ -79,12 +79,12 @@ def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatLocation

return super().de_json(data=data, bot=bot)

MIN_ADDRESS: ClassVar[int] = constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS
MIN_ADDRESS: Final[int] = constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS
""":const:`telegram.constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS`

.. versionadded:: 20.0
"""
MAX_ADDRESS: ClassVar[int] = constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS
MAX_ADDRESS: Final[int] = constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS
""":const:`telegram.constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS`

.. versionadded:: 20.0
Expand Down
14 changes: 7 additions & 7 deletions telegram/_chatmember.py
Expand Up @@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ChatMember."""
import datetime
from typing import TYPE_CHECKING, ClassVar, Dict, Optional, Type
from typing import TYPE_CHECKING, Dict, Final, Optional, Type

from telegram import constants
from telegram._telegramobject import TelegramObject
Expand Down Expand Up @@ -74,17 +74,17 @@ class ChatMember(TelegramObject):

__slots__ = ("user", "status")

ADMINISTRATOR: ClassVar[str] = constants.ChatMemberStatus.ADMINISTRATOR
ADMINISTRATOR: Final[str] = constants.ChatMemberStatus.ADMINISTRATOR
""":const:`telegram.constants.ChatMemberStatus.ADMINISTRATOR`"""
OWNER: ClassVar[str] = constants.ChatMemberStatus.OWNER
OWNER: Final[str] = constants.ChatMemberStatus.OWNER
""":const:`telegram.constants.ChatMemberStatus.OWNER`"""
BANNED: ClassVar[str] = constants.ChatMemberStatus.BANNED
BANNED: Final[str] = constants.ChatMemberStatus.BANNED
""":const:`telegram.constants.ChatMemberStatus.BANNED`"""
LEFT: ClassVar[str] = constants.ChatMemberStatus.LEFT
LEFT: Final[str] = constants.ChatMemberStatus.LEFT
""":const:`telegram.constants.ChatMemberStatus.LEFT`"""
MEMBER: ClassVar[str] = constants.ChatMemberStatus.MEMBER
MEMBER: Final[str] = constants.ChatMemberStatus.MEMBER
""":const:`telegram.constants.ChatMemberStatus.MEMBER`"""
RESTRICTED: ClassVar[str] = constants.ChatMemberStatus.RESTRICTED
RESTRICTED: Final[str] = constants.ChatMemberStatus.RESTRICTED
""":const:`telegram.constants.ChatMemberStatus.RESTRICTED`"""

def __init__(
Expand Down