# PACKAGING [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] dynamic = ["version"] name = "python-telegram-bot" description = "We have made you a wrapper you can't refuse" readme = "README.rst" requires-python = ">=3.9" license = "LGPL-3.0-only" license-files = { paths = ["LICENSE", "LICENSE.dual", "LICENSE.lesser"] } authors = [ { name = "Leandro Toledo", email = "devs@python-telegram-bot.org" } ] keywords = [ "python", "telegram", "bot", "api", "wrapper", ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Operating System :: OS Independent", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Communications :: Chat", "Topic :: Internet", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] dependencies = [ "httpx ~= 0.27", ] [project.urls] "Homepage" = "https://python-telegram-bot.org" "Documentation" = "https://docs.python-telegram-bot.org" "Bug Tracker" = "https://github.com/python-telegram-bot/python-telegram-bot/issues" "Source Code" = "https://github.com/python-telegram-bot/python-telegram-bot" "News" = "https://t.me/pythontelegrambotchannel" "Changelog" = "https://docs.python-telegram-bot.org/en/stable/changelog.html" "Support" = "https://t.me/pythontelegrambotgroup" [project.optional-dependencies] # Make sure to install those as additional_dependencies in the # pre-commit hooks for pylint & mypy # Also update the readme accordingly # # When dependencies release new versions and tests succeed, we should try to expand the allowed # versions and only increase the lower bound if necessary # # When adding new groups, make sure to update `ext` and `all` accordingly # Optional dependencies for production all = [ "python-telegram-bot[ext,http2,passport,socks]", ] callback-data = [ # Cachetools doesn't have a strict stability policy. Let's be cautious for now. "cachetools>=5.3.3,<5.6.0", ] ext = [ "python-telegram-bot[callback-data,job-queue,rate-limiter,webhooks]", ] http2 = [ "httpx[http2]", ] job-queue = [ # APS doesn't have a strict stability policy. Let's be cautious for now. "APScheduler~=3.10.4", # pytz is required by APS and just needs the lower bound due to #2120 "pytz>=2018.6", ] passport = [ "cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3,>=39.0.1", # cffi is a dependency of cryptography and added support for python 3.13 in 1.17.0rc1 "cffi >= 1.17.0rc1; python_version > '3.12'" ] rate-limiter = [ "aiolimiter~=1.1.0", ] socks = [ "httpx[socks]", ] webhooks = [ # tornado is rather stable, but let's not allow the next major release without prior testing "tornado~=6.4", ] # HATCH [tool.hatch.version] # dynamically evaluates the `__version__` variable in that file source = "code" path = "telegram/_version.py" search-paths = ["telegram"] [tool.hatch.build] packages = ["telegram"] # BLACK: [tool.black] line-length = 99 # ISORT: [tool.isort] # black config profile = "black" line_length = 99 # RUFF: [tool.ruff] line-length = 99 show-fixes = true [tool.ruff.lint] preview = true explicit-preview-rules = true # TODO: Drop this when RUF022 and RUF023 are out of preview ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"] select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE", "G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "RUF022", "RUF023", "Q", "INP", "W", "YTT", "DTZ", "ARG", "T20", "FURB", "DOC", "TRY", "D100", "D101", "D102", "D103", "D300", "D418", "D419", "S"] # Add "A (flake8-builtins)" after we drop pylint [tool.ruff.lint.per-file-ignores] "tests/*.py" = ["B018"] "tests/**.py" = ["RUF012", "ASYNC230", "DTZ", "ARG", "T201", "ASYNC109", "D", "S", "TRY"] "telegram/**.py" = ["TRY003"] "telegram/ext/_applicationbuilder.py" = ["TRY004"] "telegram/ext/filters.py" = ["D102"] "docs/**.py" = ["INP001", "ARG", "D", "TRY003", "S"] "examples/**.py" = ["ARG", "D", "S105", "TRY003"] [tool.ruff.lint.pydocstyle] convention = "google" # PYLINT: [tool.pylint."messages control"] enable = ["useless-suppression"] disable = ["duplicate-code", "too-many-arguments", "too-many-public-methods", "too-few-public-methods", "broad-exception-caught", "too-many-instance-attributes", "fixme", "missing-function-docstring", "missing-class-docstring", "too-many-locals", "too-many-lines", "too-many-branches", "too-many-statements", "cyclic-import" ] [tool.pylint.main] # run pylint across multiple cpu cores to speed it up- # https://pylint.pycqa.org/en/latest/user_guide/run.html?#parallel-execution to know more jobs = 0 [tool.pylint.classes] exclude-protected = ["_unfrozen"] # PYTEST: [tool.pytest.ini_options] testpaths = ["tests"] addopts = "--no-success-flaky-report -rX" filterwarnings = [ "error", "ignore::DeprecationWarning", 'ignore:Tasks created via `Application\.create_task` while the application is not running', "ignore::ResourceWarning", # TODO: Write so good code that we don't need to ignore ResourceWarnings anymore # Unfortunately due to https://github.com/pytest-dev/pytest/issues/8343 we can't have this here # and instead do a trick directly in tests/conftest.py # ignore::telegram.utils.deprecate.TelegramDeprecationWarning ] markers = [ "dev", # If you want to test a specific test, use this "no_req", "req", ] asyncio_mode = "auto" log_format = "%(funcName)s - Line %(lineno)d - %(message)s" # log_level = "DEBUG" # uncomment to see DEBUG logs # MYPY: [tool.mypy] warn_unused_ignores = true warn_unused_configs = true disallow_untyped_defs = true disallow_incomplete_defs = true disallow_untyped_decorators = true show_error_codes = true python_version = "3.9" # For some files, it's easier to just disable strict-optional all together instead of # cluttering the code with `# type: ignore`s or stuff like # `if self.text is None: raise RuntimeError()` [[tool.mypy.overrides]] module = [ "telegram._callbackquery", "telegram._file", "telegram._message", "telegram._files.file" ] strict_optional = false # type hinting for asyncio in webhookhandler is a bit tricky because it depends on the OS [[tool.mypy.overrides]] module = "telegram.ext._utils.webhookhandler" warn_unused_ignores = false # The libs listed below are only used for the `customwebhookbot_*.py` examples # let's just ignore type checking for them for now [[tool.mypy.overrides]] module = [ "flask.*", "quart.*", "starlette.*", "uvicorn.*", "asgiref.*", "django.*", "apscheduler.*", # not part of `customwebhookbot_*.py` examples ] ignore_missing_imports = true # COVERAGE: [tool.coverage.run] branch = true source = ["telegram"] parallel = true concurrency = ["thread", "multiprocessing"] omit = [ "tests/", "telegram/__main__.py" ] [tool.coverage.report] exclude_also = [ "@overload", "@abstractmethod", "if TYPE_CHECKING:" ]