Skip to content

Remove support for Python 3.9 #4827

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

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open

Remove support for Python 3.9 #4827

wants to merge 15 commits into from

Conversation

harshil21
Copy link
Member

@harshil21 harshil21 commented Jun 13, 2025

To be merged after #4825 and after python 3.9 reaches EOL in October

A lot of find and replace along with copilot agent edits.

Didn't use the new TypeGuard feature yet. match statements is also not used right now.

@harshil21 harshil21 requested review from Bibo-Joshi and Copilot June 13, 2025 21:15
@harshil21 harshil21 added the 🔗 python related technology: python label Jun 13, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes support for Python 3.9 and fully adopts Python 3.10+ syntax and tooling.

  • Migrated all Optional[...] and Union[...] type hints to PEP 604 union syntax (X | None, A | B).
  • Updated project configuration, CI, pre-commit, and documentation to require Python >= 3.10.
  • Adjusted examples and docs to match the new minimum Python version.

Reviewed Changes

Copilot reviewed 218 out of 218 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/telegram/_chatfullinfo.py Switched Optional[...] annotations to PEP 604 union syntax.
src/telegram/_chatboost.py Updated api_kwargs and type hints to union syntax in boost classes.
src/telegram/_chatbackground.py Migrated Optional to union syntax for chat background classes.
src/telegram/_chatadministratorrights.py Replaced Optional[bool] with `bool
src/telegram/_callbackquery.py Updated function signatures and return types to union syntax.
src/telegram/_business.py Converted Optional annotations to union syntax in business classes.
src/telegram/_botname.py Adjusted api_kwargs type to union syntax.
src/telegram/_botdescription.py Changed api_kwargs annotation to union syntax in description classes.
src/telegram/_botcommandscope.py Removed legacy Optional/Union imports and applied union annotations.
src/telegram/_botcommand.py Updated api_kwargs annotation to union syntax in bot command.
src/telegram/_birthdate.py Migrated Optional[int] to `int
src/telegram/main.py Changed _git_revision return type to `str
pyproject.toml Bumped requires-python to >=3.10 and updated Python version fields.
examples/contexttypesbot.py Updated example optional parameters to union syntax.
examples/chatmemberbot.py Changed return type of extract_status_change to union syntax.
docs/auxil/admonition_inserter.py Adjusted type hints in admonition inserter for union syntax.
changes/config.py Migrated Optional to union syntax in chango config.
README.rst Updated compatibility statement to Python 3.10+.
.pre-commit-config.yaml Adjusted pyupgrade hook args to --py310-plus.
.github/workflows/unit_tests.yml Removed Python 3.9 from test matrix.
Comments suppressed due to low confidence (2)

pyproject.toml:34

  • Update the project classifiers to include Python 3.13 and 3.14 to match the CI test matrix and declared compatibility.
"Programming Language :: Python :: 3.12",

pyproject.toml:11

  • [nitpick] Consider adding an upper bound to the Python requirement (e.g., ">=3.10,<4.0") to prevent unintended installation on Python 4.x releases.
requires-python = ">=3.10"

@harshil21 harshil21 added the 📋 do-not-merge-yet work status: do-not-merge-yet label Jun 13, 2025
@harshil21
Copy link
Member Author

harshil21 commented Jun 14, 2025

So apparently python recommends using X | Y syntax but this fails in subtle ways and makes life harder in instances like these:

>>> from typing import TypeAlias
>>> a: TypeAlias = "int"
>>> def this(arg: a | None):pass
... 
Traceback (most recent call last):
  File "<python-input-3>", line 1, in <module>
    def this(arg: a | None):pass
                  ~~^~~~~~
TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'

Now doing def this(arg: "a | None"):pass will work and appear to be fine. However this fails when you try to evaluate the forward reference, which is why test_official fails right now.

TypeAlias is actually deprecated in favor of type (py 3.12+). Using that will now not error on def this(arg: a | None):pass, but still fails test_official, because the types aren't actually evaluated:

type A = int | str
b = A | float
expected = int | float | str

b == expected  # False

b = A.__value__ | float  # Force evaluation
b == expected  # True

Anyway so for now it seems we'll have to settle and keep using Optional/Union in some places...

Base automatically changed from 3.14 to master June 19, 2025 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📋 do-not-merge-yet work status: do-not-merge-yet 🔗 python related technology: python
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant