mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 15:45:13 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ebd48903b | |||
| 1cf000c806 | |||
| 150328799a | |||
| 6d7134608f | |||
| 8266870ed7 | |||
| 519dee7e0c | |||
| 753f3727aa | |||
| 892a66d0e8 | |||
| d5e5874f96 | |||
| a5dacab8a9 | |||
| 76d8eaf0f2 | |||
| 1e4f31f1bb | |||
| 3464f24129 |
@@ -0,0 +1,5 @@
|
||||
<b>We've just released {tag}</b>.
|
||||
Thank you to everyone who contributed to this release.
|
||||
As usual, upgrade using <code>pip install -U python-telegram-bot</code>.
|
||||
|
||||
The release notes can be found <a href="https://docs.python-telegram-bot.org/en/{tag}/changelog.html">here</a>.
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Create Chango Fragment
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
create-chango-fragment:
|
||||
permissions:
|
||||
# Give the default GITHUB_TOKEN write permission to commit and push the
|
||||
# added or changed files to the repository.
|
||||
contents: write
|
||||
name: create-chango-fragment
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
# Create the new fragment
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: Bibo-Joshi/chango@9d6bd9d7612eca5fab2c5161687011be59baaf19 # v0.4.0
|
||||
with:
|
||||
github-token: ${{ secrets.CHANGO_PAT }}
|
||||
query-issue-types: true
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
name: Test Documentation Build
|
||||
name: Test Admonitions Generation
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- telegram/**
|
||||
- docs/**
|
||||
- .github/workflows/docs-admonitions.yml
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@@ -11,15 +12,15 @@ on:
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
test-sphinx-build:
|
||||
name: test-sphinx-build
|
||||
test-admonitions:
|
||||
name: Test Admonitions Generation
|
||||
runs-on: ${{matrix.os}}
|
||||
permissions:
|
||||
# for uploading artifacts
|
||||
actions: write
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.10']
|
||||
python-version: ['3.12']
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
@@ -37,17 +38,4 @@ jobs:
|
||||
python -W ignore -m pip install --upgrade pip
|
||||
python -W ignore -m pip install -r requirements-dev-all.txt
|
||||
- name: Test autogeneration of admonitions
|
||||
run: pytest -v --tb=short tests/docs/admonition_inserter.py
|
||||
- name: Build docs
|
||||
run: sphinx-build docs/source docs/build/html -W --keep-going -j auto
|
||||
- name: Upload docs
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: HTML Docs
|
||||
retention-days: 7
|
||||
path: |
|
||||
# Exclude the .doctrees folder and .buildinfo file from the artifact
|
||||
# since they are not needed and add to the size
|
||||
docs/build/html/*
|
||||
!docs/build/html/.doctrees
|
||||
!docs/build/html/.buildinfo
|
||||
run: pytest -v --tb=short tests/docs/admonition_inserter.py
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.10']
|
||||
python-version: ['3.12']
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
|
||||
@@ -21,13 +21,13 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
|
||||
uses: astral-sh/setup-uv@f94ec6bedd8674c4426838e6b50417d36b6ab231 # v5.3.1
|
||||
- name: Run zizmor
|
||||
run: uvx zizmor --persona=pedantic --format sarif . > results.sarif
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
|
||||
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
pull-requests: write # for srvaroa/labeler to add labels in PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: srvaroa/labeler@fe4b1c73bb8abf2f14a44a6912a8b4fee835d631 # v1.12.0
|
||||
- uses: srvaroa/labeler@0a20eccb8c94a1ee0bed5f16859aece1c45c3e55 # v1.13.0
|
||||
# Config file at .github/labeler.yml
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3
|
||||
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
|
||||
|
||||
compute-signatures:
|
||||
name: Compute SHA1 Sums and Sign with Sigstore
|
||||
@@ -119,13 +119,14 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# Create a tag and a GitHub Release. The description can be changed later, as for now
|
||||
# we don't define it through this workflow.
|
||||
# Create a tag and a GitHub Release. The description is filled by the static template, we
|
||||
# just insert the correct tag in the template.
|
||||
run: >-
|
||||
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
|
||||
gh release create
|
||||
"$TAG"
|
||||
--repo '${{ github.repository }}'
|
||||
--generate-notes
|
||||
--notes-file -
|
||||
- name: Upload artifact signatures to GitHub Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
@@ -137,3 +138,27 @@ jobs:
|
||||
gh release upload
|
||||
"$TAG" dist/**
|
||||
--repo '${{ github.repository }}'
|
||||
|
||||
telegram-channel:
|
||||
name: Publish to Telegram Channel
|
||||
needs:
|
||||
- github-release
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: release_pypi
|
||||
permissions: {}
|
||||
|
||||
steps:
|
||||
- name: Publish to Telegram Channel
|
||||
env:
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# This secret is configured only for the `pypi-release` branch
|
||||
BOT_TOKEN: ${{ secrets.CHANNEL_BOT_TOKEN }}
|
||||
run: >-
|
||||
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
|
||||
curl
|
||||
-X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage"
|
||||
-d "chat_id=@pythontelegrambotchannel"
|
||||
-d "parse_mode=HTML"
|
||||
--data-urlencode "text@-"
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
- name: Publish to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3
|
||||
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
|
||||
@@ -121,14 +121,15 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.build.outputs.TAG }}
|
||||
# Create a GitHub Release *draft*. The description can be changed later, as for now
|
||||
# we don't define it through this workflow.
|
||||
# Create a tag and a GitHub Release *draft*. The description is filled by the static
|
||||
# template, we just insert the correct tag in the template.
|
||||
run: >-
|
||||
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
|
||||
gh release create
|
||||
"$TAG"
|
||||
--repo '${{ github.repository }}'
|
||||
--generate-notes
|
||||
--draft
|
||||
--notes-file -
|
||||
- name: Upload artifact signatures to GitHub Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
- requirements: docs/requirements-docs.txt
|
||||
- requirements: requirements-dev-all.txt
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
breaking = """This release removes all functionality that was deprecated in v20.x. This is in line with our :ref:`stability policy <stability-policy>`.
|
||||
This includes the following changes:
|
||||
|
||||
- Removed ``filters.CHAT`` (all messages have an associated chat) and ``filters.StatusUpdate.USER_SHARED`` (use ``filters.StatusUpdate.USERS_SHARED`` instead).
|
||||
- Removed ``Defaults.disable_web_page_preview`` and ``Defaults.quote``. Use ``Defaults.link_preview_options`` and ``Defaults.do_quote`` instead.
|
||||
- Removed ``ApplicationBuilder.(get_updates_)proxy_url`` and ``HTTPXRequest.proxy_url``. Use ``ApplicationBuilder.(get_updates_)proxy`` and ``HTTPXRequest.proxy`` instead.
|
||||
- Removed the ``*_timeout`` arguments of ``Application.run_polling`` and ``Updater.start_webhook``. Instead, specify the values via ``ApplicationBuilder.get_updates_*_timeout``.
|
||||
- Removed ``constants.InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH``. Use ``constants.InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`` instead.
|
||||
- Removed the argument ``quote`` of ``Message.reply_*``. Use ``do_quote`` instead.
|
||||
- Removed the superfluous ``EncryptedPassportElement.credentials`` without replacement.
|
||||
- Changed attribute value of ``PassportFile.file_date`` from :obj:`int` to :class:`datetime.datetime`. Make sure to adjust your code accordingly.
|
||||
- Changed the attribute value of ``PassportElementErrors.file_hashes`` from :obj:`list` to :obj:`tuple`. Make sure to adjust your code accordingly.
|
||||
- Make ``BaseRequest.read_timeout`` an abstract property. If you subclass ``BaseRequest``, you need to implement this property.
|
||||
- The default value for ``write_timeout`` now defaults to ``DEFAULT_NONE`` also for bot methods that send media. Previously, it was ``20``. If you subclass ``BaseRequest``, make sure to use your desired write timeout if ``RequestData.multipart_data`` is set.
|
||||
"""
|
||||
[[pull_requests]]
|
||||
uid = "4671"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = ["4659"]
|
||||
@@ -0,0 +1,5 @@
|
||||
documentation = "Add `chango <https://chango.readthedocs.io/stable/>`_ As Changelog Management Tool"
|
||||
[[pull_requests]]
|
||||
uid = "4672"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = ["4321"]
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump github/codeql-action from 3.28.8 to 3.28.10"
|
||||
[[pull_requests]]
|
||||
uid = "4697"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump srvaroa/labeler from 1.12.0 to 1.13.0"
|
||||
[[pull_requests]]
|
||||
uid = "4698"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump astral-sh/setup-uv from 5.2.2 to 5.3.1"
|
||||
[[pull_requests]]
|
||||
uid = "4699"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump Bibo-Joshi/chango from 0.3.1 to 0.3.2"
|
||||
[[pull_requests]]
|
||||
uid = "4700"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4"
|
||||
[[pull_requests]]
|
||||
uid = "4701"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump pytest from 8.3.4 to 8.3.5"
|
||||
[[pull_requests]]
|
||||
uid = "4709"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump sphinx from 8.1.3 to 8.2.3"
|
||||
[[pull_requests]]
|
||||
uid = "4710"
|
||||
author_uid = "dependabot[bot]"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump Bibo-Joshi/chango from 0.3.2 to 0.4.0"
|
||||
[[pull_requests]]
|
||||
uid = "4712"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Bump Version to v22.0"
|
||||
[[pull_requests]]
|
||||
uid = "4719"
|
||||
author_uid = "Bibo-Joshi"
|
||||
closes_threads = []
|
||||
@@ -1,8 +1,14 @@
|
||||
.. _ptb-changelog:
|
||||
Version 21.11.1
|
||||
===============
|
||||
|
||||
=========
|
||||
Changelog
|
||||
=========
|
||||
*Released 2025-03-01*
|
||||
|
||||
This is the technical changelog for version 21.11. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
|
||||
|
||||
Documentation Improvements
|
||||
--------------------------
|
||||
|
||||
- Fix ReadTheDocs Build (:pr:`4695`)
|
||||
|
||||
Version 21.11
|
||||
=============
|
||||
@@ -0,0 +1,78 @@
|
||||
# noqa: INP001
|
||||
# pylint: disable=import-error
|
||||
"""Configuration for the chango changelog tool"""
|
||||
|
||||
from collections.abc import Collection
|
||||
from typing import Optional
|
||||
|
||||
from chango.concrete import DirectoryChanGo, DirectoryVersionScanner, HeaderVersionHistory
|
||||
from chango.concrete.sections import GitHubSectionChangeNote, Section, SectionVersionNote
|
||||
|
||||
version_scanner = DirectoryVersionScanner(base_directory=".", unreleased_directory="unreleased")
|
||||
|
||||
|
||||
class ChangoSectionChangeNote(
|
||||
GitHubSectionChangeNote.with_sections( # type: ignore[misc]
|
||||
[
|
||||
Section(uid="highlights", title="Highlights", sort_order=0),
|
||||
Section(uid="breaking", title="Breaking Changes", sort_order=1),
|
||||
Section(uid="security", title="Security Changes", sort_order=2),
|
||||
Section(uid="deprecations", title="Deprecations", sort_order=3),
|
||||
Section(uid="features", title="New Features", sort_order=4),
|
||||
Section(uid="bugfixes", title="Bug Fixes", sort_order=5),
|
||||
Section(uid="dependencies", title="Dependencies", sort_order=6),
|
||||
Section(uid="other", title="Other Changes", sort_order=7),
|
||||
Section(uid="documentation", title="Documentation", sort_order=8),
|
||||
Section(uid="internal", title="Internal Changes", sort_order=9),
|
||||
]
|
||||
)
|
||||
):
|
||||
"""Custom change note type for PTB. Mainly overrides get_sections to map labels to sections"""
|
||||
|
||||
OWNER = "python-telegram-bot"
|
||||
REPOSITORY = "python-telegram-bot"
|
||||
|
||||
@classmethod
|
||||
def get_sections(
|
||||
cls,
|
||||
labels: Collection[str],
|
||||
issue_types: Optional[Collection[str]],
|
||||
) -> set[str]:
|
||||
"""Override get_sections to have customized auto-detection of relevant sections based on
|
||||
the pull request and linked issues. Certainly not perfect in all cases, but should be a
|
||||
good start for most PRs.
|
||||
"""
|
||||
combined_labels = set(labels) | (set(issue_types or []))
|
||||
|
||||
mapping = {
|
||||
"🐛 bug": "bugfixes",
|
||||
"💡 feature": "features",
|
||||
"🧹 chore": "internal",
|
||||
"⚙️ bot-api": "features",
|
||||
"⚙️ documentation": "documentation",
|
||||
"⚙️ tests": "internal",
|
||||
"⚙️ ci-cd": "internal",
|
||||
"⚙️ security": "security",
|
||||
"⚙️ examples": "documentation",
|
||||
"⚙️ type-hinting": "other",
|
||||
"🛠 refactor": "internal",
|
||||
"🛠 breaking": "breaking",
|
||||
"⚙️ dependencies": "dependencies",
|
||||
"🔗 github-actions": "internal",
|
||||
"🛠 code-quality": "internal",
|
||||
}
|
||||
|
||||
# we want to return *all* from the mapping that are in the combined_labels
|
||||
# removing superfluous sections from the fragment is a tad easier than adding them
|
||||
found = {section for label, section in mapping.items() if label in combined_labels}
|
||||
|
||||
# if we have not found any sections, we default to "other"
|
||||
return found or {"other"}
|
||||
|
||||
|
||||
chango_instance = DirectoryChanGo(
|
||||
change_note_type=ChangoSectionChangeNote,
|
||||
version_note_type=SectionVersionNote,
|
||||
version_history_type=HeaderVersionHistory,
|
||||
scanner=version_scanner,
|
||||
)
|
||||
@@ -47,29 +47,29 @@ keyword_args = [
|
||||
"",
|
||||
]
|
||||
|
||||
media_write_timeout_deprecation_methods = [
|
||||
"send_photo",
|
||||
media_write_timeout_change_methods = [
|
||||
"add_sticker_to_set",
|
||||
"create_new_sticker_set",
|
||||
"send_animation",
|
||||
"send_audio",
|
||||
"send_document",
|
||||
"send_media_group",
|
||||
"send_photo",
|
||||
"send_sticker",
|
||||
"send_video",
|
||||
"send_video_note",
|
||||
"send_animation",
|
||||
"send_voice",
|
||||
"send_media_group",
|
||||
"set_chat_photo",
|
||||
"upload_sticker_file",
|
||||
"add_sticker_to_set",
|
||||
"create_new_sticker_set",
|
||||
]
|
||||
media_write_timeout_deprecation = [
|
||||
media_write_timeout_change = [
|
||||
" write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.write_timeout`. By default, ``20`` "
|
||||
" seconds are used as write timeout."
|
||||
"",
|
||||
"",
|
||||
" .. deprecated:: 20.7",
|
||||
" In future versions, the default value will be changed to "
|
||||
" .. versionchanged:: 22.0",
|
||||
" The default value changed to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
"",
|
||||
"",
|
||||
|
||||
@@ -32,8 +32,8 @@ from docs.auxil.kwargs_insertion import (
|
||||
find_insert_pos_for_kwargs,
|
||||
get_updates_read_timeout_addition,
|
||||
keyword_args,
|
||||
media_write_timeout_deprecation,
|
||||
media_write_timeout_deprecation_methods,
|
||||
media_write_timeout_change,
|
||||
media_write_timeout_change_methods,
|
||||
)
|
||||
from docs.auxil.link_code import LINE_NUMBERS
|
||||
|
||||
@@ -116,9 +116,9 @@ def autodoc_process_docstring(
|
||||
|
||||
if (
|
||||
"post.write_timeout`. Defaults to" in to_insert
|
||||
and method_name in media_write_timeout_deprecation_methods
|
||||
and method_name in media_write_timeout_change_methods
|
||||
):
|
||||
effective_insert: list[str] = media_write_timeout_deprecation
|
||||
effective_insert: list[str] = media_write_timeout_change
|
||||
elif get_updates and to_insert.lstrip().startswith("read_timeout"):
|
||||
effective_insert = [to_insert, *get_updates_read_timeout_addition]
|
||||
else:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
sphinx==8.1.3
|
||||
chango~=0.4.0
|
||||
sphinx==8.2.3
|
||||
furo==2024.8.6
|
||||
furo-sphinx-search @ git+https://github.com/harshil21/furo-sphinx-search@v0.2.0.1
|
||||
sphinx-paramlinks==0.6.0
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
.. include:: ../../CHANGES.rst
|
||||
.. _ptb-changelog:
|
||||
|
||||
=========
|
||||
Changelog
|
||||
=========
|
||||
|
||||
.. chango::
|
||||
|
||||
.. include:: ../../changes/LEGACY.rst
|
||||
@@ -8,6 +8,11 @@ from pathlib import Path
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
if sys.version_info < (3, 12):
|
||||
# Due to dependency on chango
|
||||
raise RuntimeError("This documentation needs at least Python 3.12")
|
||||
|
||||
|
||||
sys.path.insert(0, str(Path("../..").resolve().absolute()))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
@@ -36,6 +41,7 @@ needs_sphinx = "8.1.3"
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"chango.sphinx_ext",
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx.ext.intersphinx",
|
||||
@@ -52,6 +58,9 @@ extensions = [
|
||||
if os.environ.get("READTHEDOCS", "") == "True":
|
||||
extensions.append("sphinx_build_compatibility.extension")
|
||||
|
||||
# Configuration for the chango sphinx directive
|
||||
chango_pyproject_toml_path = Path(__file__).parent.parent.parent
|
||||
|
||||
# For shorter links to Wiki in docstrings
|
||||
extlinks = {
|
||||
"wiki": ("https://github.com/python-telegram-bot/python-telegram-bot/wiki/%s", "%s"),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _stability-policy:
|
||||
|
||||
Stability Policy
|
||||
================
|
||||
|
||||
|
||||
@@ -105,6 +105,11 @@ search-paths = ["telegram"]
|
||||
[tool.hatch.build]
|
||||
packages = ["telegram"]
|
||||
|
||||
# CHANGO
|
||||
[tool.chango]
|
||||
sys_path = "changes"
|
||||
chango_instance = { name= "chango_instance", module = "config" }
|
||||
|
||||
# BLACK:
|
||||
[tool.black]
|
||||
line-length = 99
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
build
|
||||
|
||||
# For the test suite
|
||||
pytest==8.3.4
|
||||
pytest==8.3.5
|
||||
|
||||
# needed because pytest doesn't come with native support for coroutines as tests
|
||||
pytest-asyncio==0.21.2
|
||||
|
||||
+2
-14
@@ -112,7 +112,7 @@ from telegram.error import EndPointNotFound, InvalidToken
|
||||
from telegram.request import BaseRequest, RequestData
|
||||
from telegram.request._httpxrequest import HTTPXRequest
|
||||
from telegram.request._requestparameter import RequestParameter
|
||||
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
|
||||
from telegram.warnings import PTBUserWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import (
|
||||
@@ -4581,19 +4581,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
if not isinstance(read_timeout, DefaultValue):
|
||||
arg_read_timeout: float = read_timeout or 0
|
||||
else:
|
||||
try:
|
||||
arg_read_timeout = self._request[0].read_timeout or 0
|
||||
except NotImplementedError:
|
||||
arg_read_timeout = 2
|
||||
self._warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
f"The class {self._request[0].__class__.__name__} does not override "
|
||||
"the property `read_timeout`. Overriding this property will be mandatory "
|
||||
"in future versions. Using 2 seconds as fallback.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
arg_read_timeout = self._request[0].read_timeout or 0
|
||||
|
||||
# Ideally we'd use an aggressive read timeout for the polling. However,
|
||||
# * Short polling should return within 2 seconds.
|
||||
|
||||
@@ -62,6 +62,12 @@ class InlineQuery(TelegramObject):
|
||||
``auto_pagination``. Use a named argument for those,
|
||||
and notice that some positional arguments changed position as a result.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed constants ``MIN_START_PARAMETER_LENGTH`` and ``MAX_START_PARAMETER_LENGTH``.
|
||||
Use :attr:`telegram.constants.InlineQueryResultsButtonLimit.MIN_START_PARAMETER_LENGTH` and
|
||||
:attr:`telegram.constants.InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`
|
||||
instead.
|
||||
|
||||
Args:
|
||||
id (:obj:`str`): Unique identifier for this query.
|
||||
from_user (:class:`telegram.User`): Sender.
|
||||
@@ -202,16 +208,6 @@ class InlineQuery(TelegramObject):
|
||||
|
||||
.. versionadded:: 13.2
|
||||
"""
|
||||
MIN_SWITCH_PM_TEXT_LENGTH: Final[int] = constants.InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH
|
||||
""":const:`telegram.constants.InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_SWITCH_PM_TEXT_LENGTH: Final[int] = constants.InlineQueryLimit.MAX_SWITCH_PM_TEXT_LENGTH
|
||||
""":const:`telegram.constants.InlineQueryLimit.MAX_SWITCH_PM_TEXT_LENGTH`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_OFFSET_LENGTH: Final[int] = constants.InlineQueryLimit.MAX_OFFSET_LENGTH
|
||||
""":const:`telegram.constants.InlineQueryLimit.MAX_OFFSET_LENGTH`
|
||||
|
||||
|
||||
@@ -47,9 +47,10 @@ class InlineQueryResultsButton(TelegramObject):
|
||||
inside the Web App.
|
||||
start_parameter (:obj:`str`, optional): Deep-linking parameter for the
|
||||
:guilabel:`/start` message sent to the bot when user presses the switch button.
|
||||
:tg-const:`telegram.InlineQuery.MIN_SWITCH_PM_TEXT_LENGTH`-
|
||||
:tg-const:`telegram.InlineQuery.MAX_SWITCH_PM_TEXT_LENGTH` characters,
|
||||
only ``A-Z``, ``a-z``, ``0-9``, ``_`` and ``-`` are allowed.
|
||||
:tg-const:`telegram.constants.InlineQueryResultsButtonLimit.MIN_START_PARAMETER_LENGTH`
|
||||
-
|
||||
:tg-const:`telegram.constants.InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`
|
||||
characters, only ``A-Z``, ``a-z``, ``0-9``, ``_`` and ``-`` are allowed.
|
||||
|
||||
Example:
|
||||
An inline bot that sends YouTube videos can ask the user to connect the bot to
|
||||
@@ -67,10 +68,10 @@ class InlineQueryResultsButton(TelegramObject):
|
||||
user presses the button. The Web App will be able to switch back to the inline mode
|
||||
using the method ``web_app_switch_inline_query`` inside the Web App.
|
||||
start_parameter (:obj:`str`): Optional. Deep-linking parameter for the
|
||||
:guilabel:`/start` message sent to the bot when user presses the switch button.
|
||||
:tg-const:`telegram.InlineQuery.MIN_SWITCH_PM_TEXT_LENGTH`-
|
||||
:tg-const:`telegram.InlineQuery.MAX_SWITCH_PM_TEXT_LENGTH` characters,
|
||||
only ``A-Z``, ``a-z``, ``0-9``, ``_`` and ``-`` are allowed.
|
||||
:tg-const:`telegram.constants.InlineQueryResultsButtonLimit.MIN_START_PARAMETER_LENGTH`
|
||||
-
|
||||
:tg-const:`telegram.constants.InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`
|
||||
characters, only ``A-Z``, ``a-z``, ``0-9``, ``_`` and ``-`` are allowed.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
+96
-156
@@ -930,6 +930,9 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
.. |reply_same_thread| replace:: If :paramref:`message_thread_id` is not provided,
|
||||
this will reply to the same thread (topic) of the original message.
|
||||
|
||||
.. |quote_removed| replace:: Removed deprecated parameter ``quote``. Use :paramref:`do_quote`
|
||||
instead.
|
||||
"""
|
||||
|
||||
# fmt: on
|
||||
@@ -1484,22 +1487,17 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
return self._effective_attachment # type: ignore[return-value]
|
||||
|
||||
def _quote(
|
||||
self, quote: Optional[bool], reply_to_message_id: Optional[int] = None
|
||||
) -> Optional[ReplyParameters]:
|
||||
def _do_quote(self, do_quote: Optional[bool]) -> Optional[ReplyParameters]:
|
||||
"""Modify kwargs for replying with or without quoting."""
|
||||
if reply_to_message_id is not None:
|
||||
return ReplyParameters(reply_to_message_id)
|
||||
|
||||
if quote is not None:
|
||||
if quote:
|
||||
if do_quote is not None:
|
||||
if do_quote:
|
||||
return ReplyParameters(self.message_id)
|
||||
|
||||
else:
|
||||
# Unfortunately we need some ExtBot logic here because it's hard to move shortcut
|
||||
# logic into ExtBot
|
||||
if hasattr(self.get_bot(), "defaults") and self.get_bot().defaults: # type: ignore
|
||||
default_quote = self.get_bot().defaults.quote # type: ignore[attr-defined]
|
||||
default_quote = self.get_bot().defaults.do_quote # type: ignore[attr-defined]
|
||||
else:
|
||||
default_quote = None
|
||||
if (default_quote is None and self.chat.type != Chat.PRIVATE) or default_quote:
|
||||
@@ -1675,29 +1673,14 @@ class Message(MaybeInaccessibleMessage):
|
||||
async def _parse_quote_arguments(
|
||||
self,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]],
|
||||
quote: Optional[bool],
|
||||
reply_to_message_id: Optional[int],
|
||||
reply_parameters: Optional["ReplyParameters"],
|
||||
) -> tuple[Union[str, int], ReplyParameters]:
|
||||
if quote and do_quote:
|
||||
raise ValueError("The arguments `quote` and `do_quote` are mutually exclusive")
|
||||
|
||||
if reply_to_message_id is not None and reply_parameters is not None:
|
||||
raise ValueError(
|
||||
"`reply_to_message_id` and `reply_parameters` are mutually exclusive."
|
||||
)
|
||||
|
||||
if quote is not None:
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.8",
|
||||
"The `quote` parameter is deprecated in favor of the `do_quote` parameter. "
|
||||
"Please update your code to use `do_quote` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
effective_do_quote = quote or do_quote
|
||||
chat_id: Union[str, int] = self.chat_id
|
||||
|
||||
# reply_parameters and reply_to_message_id overrule the do_quote parameter
|
||||
@@ -1705,11 +1688,11 @@ class Message(MaybeInaccessibleMessage):
|
||||
effective_reply_parameters = reply_parameters
|
||||
elif reply_to_message_id is not None:
|
||||
effective_reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
elif isinstance(effective_do_quote, dict):
|
||||
effective_reply_parameters = effective_do_quote["reply_parameters"]
|
||||
chat_id = effective_do_quote["chat_id"]
|
||||
elif isinstance(do_quote, dict):
|
||||
effective_reply_parameters = do_quote["reply_parameters"]
|
||||
chat_id = do_quote["chat_id"]
|
||||
else:
|
||||
effective_reply_parameters = self._quote(effective_do_quote)
|
||||
effective_reply_parameters = self._do_quote(do_quote)
|
||||
|
||||
return chat_id, effective_reply_parameters
|
||||
|
||||
@@ -1750,7 +1733,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
disable_web_page_preview: Optional[bool] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1773,11 +1755,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -1788,7 +1769,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_message(
|
||||
@@ -1830,7 +1811,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
disable_web_page_preview: Optional[bool] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1856,15 +1836,14 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
Note:
|
||||
:tg-const:`telegram.constants.ParseMode.MARKDOWN` is a legacy mode, retained by
|
||||
Telegram for backward compatibility. You should use :meth:`reply_markdown_v2` instead.
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -1874,7 +1853,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_message(
|
||||
@@ -1916,7 +1895,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
disable_web_page_preview: Optional[bool] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1942,11 +1920,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -1956,7 +1933,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_message(
|
||||
@@ -1998,7 +1975,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
disable_web_page_preview: Optional[bool] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2024,11 +2000,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2038,7 +2013,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
:class:`telegram.Message`: On success, instance representing the message posted.
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_message(
|
||||
@@ -2078,7 +2053,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2104,11 +2078,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2121,7 +2094,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
:class:`telegram.error.TelegramError`
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_media_group(
|
||||
@@ -2164,7 +2137,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2187,11 +2159,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2202,7 +2173,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_photo(
|
||||
@@ -2251,7 +2222,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2274,11 +2244,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2289,7 +2258,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_audio(
|
||||
@@ -2338,7 +2307,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2361,11 +2329,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2376,7 +2343,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_document(
|
||||
@@ -2427,7 +2394,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2450,11 +2416,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2465,7 +2430,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_animation(
|
||||
@@ -2511,7 +2476,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2534,11 +2498,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2549,7 +2512,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_sticker(
|
||||
@@ -2598,7 +2561,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2621,11 +2583,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2636,7 +2597,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_video(
|
||||
@@ -2688,7 +2649,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2711,11 +2671,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2726,7 +2685,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_video_note(
|
||||
@@ -2770,7 +2729,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
filename: Optional[str] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2793,11 +2751,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2808,7 +2765,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_voice(
|
||||
@@ -2854,7 +2811,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
location: Optional[Location] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2877,11 +2833,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2892,7 +2847,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_location(
|
||||
@@ -2941,7 +2896,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
venue: Optional[Venue] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2964,11 +2918,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -2979,7 +2932,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_venue(
|
||||
@@ -3026,7 +2979,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
contact: Optional[Contact] = None,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3049,11 +3001,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -3064,7 +3015,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_contact(
|
||||
@@ -3116,7 +3067,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3139,11 +3089,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -3154,7 +3103,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_poll(
|
||||
@@ -3202,7 +3151,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3225,11 +3173,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -3240,7 +3187,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_dice(
|
||||
@@ -3319,7 +3266,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3342,11 +3288,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -3359,7 +3304,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_game(
|
||||
@@ -3414,7 +3359,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3436,6 +3380,9 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
Warning:
|
||||
As of API 5.2 :paramref:`start_parameter <telegram.Bot.send_invoice.start_parameter>`
|
||||
is an optional argument and therefore the
|
||||
@@ -3449,10 +3396,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
:paramref:`start_parameter <telegram.Bot.send_invoice.start_parameter>` is optional.
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -3463,7 +3406,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().send_invoice(
|
||||
@@ -3637,7 +3580,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
quote: Optional[bool] = None,
|
||||
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3660,12 +3602,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
.. versionchanged:: 21.1
|
||||
|reply_same_thread|
|
||||
|
||||
Keyword Args:
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
.. versionchanged:: 22.0
|
||||
|quote_removed|
|
||||
|
||||
.. versionadded:: 13.1
|
||||
.. deprecated:: 20.8
|
||||
This argument is deprecated in favor of :paramref:`do_quote`
|
||||
Keyword Args:
|
||||
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
|
||||
Mutually exclusive with :paramref:`quote`.
|
||||
|
||||
@@ -3676,7 +3616,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, quote, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
|
||||
return await self.get_bot().copy_message(
|
||||
@@ -3748,7 +3688,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
|
||||
"""
|
||||
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
|
||||
do_quote, None, reply_to_message_id, reply_parameters
|
||||
do_quote, reply_to_message_id, reply_parameters
|
||||
)
|
||||
return await self.get_bot().send_paid_media(
|
||||
chat_id=chat_id,
|
||||
|
||||
@@ -164,10 +164,6 @@ class EncryptedPassportElement(TelegramObject):
|
||||
reverse_side: Optional[PassportFile] = None,
|
||||
selfie: Optional[PassportFile] = None,
|
||||
translation: Optional[Sequence[PassportFile]] = None,
|
||||
# TODO: Remove the credentials argument in 22.0 or later
|
||||
credentials: Optional[ # pylint: disable=unused-argument # noqa: ARG002
|
||||
"Credentials"
|
||||
] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
# pylint: disable=redefined-builtin
|
||||
"""This module contains the classes that represent Telegram PassportElementError."""
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import Optional
|
||||
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.argumentparsing import parse_sequence_arg
|
||||
from telegram._utils.types import JSONDict
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
|
||||
class PassportElementError(TelegramObject):
|
||||
@@ -168,23 +168,30 @@ class PassportElementErrorFiles(PassportElementError):
|
||||
type (:obj:`str`): The section of the user's Telegram Passport which has the issue, one of
|
||||
``"utility_bill"``, ``"bank_statement"``, ``"rental_agreement"``,
|
||||
``"passport_registration"``, ``"temporary_registration"``.
|
||||
file_hashes (list[:obj:`str`]): List of base64-encoded file hashes.
|
||||
file_hashes (Sequence[:obj:`str`]): List of base64-encoded file hashes.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
|sequenceargs|
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): The section of the user's Telegram Passport which has the issue, one of
|
||||
``"utility_bill"``, ``"bank_statement"``, ``"rental_agreement"``,
|
||||
``"passport_registration"``, ``"temporary_registration"``.
|
||||
file_hashes (tuple[:obj:`str`]): List of base64-encoded file hashes.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
|tupleclassattrs|
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("_file_hashes",)
|
||||
__slots__ = ("file_hashes",)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
type: str,
|
||||
file_hashes: list[str],
|
||||
file_hashes: Sequence[str],
|
||||
message: str,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
@@ -192,32 +199,9 @@ class PassportElementErrorFiles(PassportElementError):
|
||||
# Required
|
||||
super().__init__("files", type, message, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
self._file_hashes: list[str] = file_hashes
|
||||
self.file_hashes: tuple[str, ...] = parse_sequence_arg(file_hashes)
|
||||
|
||||
self._id_attrs = (self.source, self.type, self.message, *tuple(file_hashes))
|
||||
|
||||
def to_dict(self, recursive: bool = True) -> JSONDict:
|
||||
"""See :meth:`telegram.TelegramObject.to_dict` for details."""
|
||||
data = super().to_dict(recursive)
|
||||
data["file_hashes"] = self._file_hashes
|
||||
return data
|
||||
|
||||
@property
|
||||
def file_hashes(self) -> list[str]:
|
||||
"""List of base64-encoded file hashes.
|
||||
|
||||
.. deprecated:: 20.6
|
||||
This attribute will return a tuple instead of a list in future major versions.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._file_hashes
|
||||
self._id_attrs = (self.source, self.type, self.message, self.file_hashes)
|
||||
|
||||
|
||||
class PassportElementErrorFrontSide(PassportElementError):
|
||||
@@ -386,7 +370,10 @@ class PassportElementErrorTranslationFiles(PassportElementError):
|
||||
one of ``"passport"``, ``"driver_license"``, ``"identity_card"``,
|
||||
``"internal_passport"``, ``"utility_bill"``, ``"bank_statement"``,
|
||||
``"rental_agreement"``, ``"passport_registration"``, ``"temporary_registration"``.
|
||||
file_hashes (list[:obj:`str`]): List of base64-encoded file hashes.
|
||||
file_hashes (Sequence[:obj:`str`]): List of base64-encoded file hashes.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
|sequenceargs|
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
Attributes:
|
||||
@@ -394,16 +381,20 @@ class PassportElementErrorTranslationFiles(PassportElementError):
|
||||
one of ``"passport"``, ``"driver_license"``, ``"identity_card"``,
|
||||
``"internal_passport"``, ``"utility_bill"``, ``"bank_statement"``,
|
||||
``"rental_agreement"``, ``"passport_registration"``, ``"temporary_registration"``.
|
||||
file_hashes (tuple[:obj:`str`]): List of base64-encoded file hashes.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
|tupleclassattrs|
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("_file_hashes",)
|
||||
__slots__ = ("file_hashes",)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
type: str,
|
||||
file_hashes: list[str],
|
||||
file_hashes: Sequence[str],
|
||||
message: str,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
@@ -411,33 +402,9 @@ class PassportElementErrorTranslationFiles(PassportElementError):
|
||||
# Required
|
||||
super().__init__("translation_files", type, message, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
self._file_hashes: list[str] = file_hashes
|
||||
self.file_hashes: tuple[str, ...] = parse_sequence_arg(file_hashes)
|
||||
|
||||
self._id_attrs = (self.source, self.type, self.message, *tuple(file_hashes))
|
||||
|
||||
def to_dict(self, recursive: bool = True) -> JSONDict:
|
||||
"""See :meth:`telegram.TelegramObject.to_dict` for details."""
|
||||
data = super().to_dict(recursive)
|
||||
data["file_hashes"] = self._file_hashes
|
||||
return data
|
||||
|
||||
@property
|
||||
def file_hashes(self) -> list[str]:
|
||||
"""List of base64-encoded file hashes.
|
||||
|
||||
.. deprecated:: 20.6
|
||||
This attribute will return a tuple instead of a list in future major versions.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions. See the stability policy:"
|
||||
" https://docs.python-telegram-bot.org/en/stable/stability_policy.html",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._file_hashes
|
||||
self._id_attrs = (self.source, self.type, self.message, self.file_hashes)
|
||||
|
||||
|
||||
class PassportElementErrorUnspecified(PassportElementError):
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Encrypted PassportFile."""
|
||||
|
||||
import datetime as dtm
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram._utils.types import JSONDict, ODVInput
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot, File, FileCredentials
|
||||
@@ -45,11 +45,11 @@ class PassportFile(TelegramObject):
|
||||
is supposed to be the same over time and for different bots.
|
||||
Can't be used to download or reuse the file.
|
||||
file_size (:obj:`int`): File size in bytes.
|
||||
file_date (:obj:`int`): Unix time when the file was uploaded.
|
||||
file_date (:class:`datetime.datetime`): Time when the file was uploaded.
|
||||
|
||||
.. deprecated:: 20.6
|
||||
This argument will only accept a datetime instead of an integer in future
|
||||
major versions.
|
||||
.. versionchanged:: 22.0
|
||||
Accepts only :class:`datetime.datetime` instead of :obj:`int`.
|
||||
|datetime_localization|
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
@@ -58,11 +58,16 @@ class PassportFile(TelegramObject):
|
||||
is supposed to be the same over time and for different bots.
|
||||
Can't be used to download or reuse the file.
|
||||
file_size (:obj:`int`): File size in bytes.
|
||||
file_date (:class:`datetime.datetime`): Time when the file was uploaded.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Returns :class:`datetime.datetime` instead of :obj:`int`.
|
||||
|datetime_localization|
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"_credentials",
|
||||
"_file_date",
|
||||
"file_date",
|
||||
"file_id",
|
||||
"file_size",
|
||||
"file_unique_id",
|
||||
@@ -72,7 +77,7 @@ class PassportFile(TelegramObject):
|
||||
self,
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
file_date: int,
|
||||
file_date: dtm.datetime,
|
||||
file_size: int,
|
||||
credentials: Optional["FileCredentials"] = None,
|
||||
*,
|
||||
@@ -84,7 +89,7 @@ class PassportFile(TelegramObject):
|
||||
self.file_id: str = file_id
|
||||
self.file_unique_id: str = file_unique_id
|
||||
self.file_size: int = file_size
|
||||
self._file_date: int = file_date
|
||||
self.file_date: dtm.datetime = file_date
|
||||
# Optionals
|
||||
|
||||
self._credentials: Optional[FileCredentials] = credentials
|
||||
@@ -93,28 +98,16 @@ class PassportFile(TelegramObject):
|
||||
|
||||
self._freeze()
|
||||
|
||||
def to_dict(self, recursive: bool = True) -> JSONDict:
|
||||
"""See :meth:`telegram.TelegramObject.to_dict` for details."""
|
||||
data = super().to_dict(recursive)
|
||||
data["file_date"] = self._file_date
|
||||
return data
|
||||
@classmethod
|
||||
def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportFile":
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
@property
|
||||
def file_date(self) -> int:
|
||||
""":obj:`int`: Unix time when the file was uploaded.
|
||||
# Get the local timezone from the bot if it has defaults
|
||||
loc_tzinfo = extract_tzinfo_from_defaults(bot)
|
||||
data["file_date"] = from_timestamp(data.get("file_date"), tzinfo=loc_tzinfo)
|
||||
|
||||
.. deprecated:: 20.6
|
||||
This attribute will return a datetime instead of a integer in future major versions.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"The attribute `file_date` will return a datetime instead of an integer in future"
|
||||
" major versions.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._file_date
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
@classmethod
|
||||
def de_json_decrypted(
|
||||
|
||||
@@ -51,6 +51,6 @@ class Version(NamedTuple):
|
||||
|
||||
|
||||
__version_info__: Final[Version] = Version(
|
||||
major=21, minor=11, micro=0, releaselevel="final", serial=0
|
||||
major=22, minor=0, micro=0, releaselevel="final", serial=0
|
||||
)
|
||||
__version__: Final[str] = str(__version_info__)
|
||||
|
||||
+8
-18
@@ -1375,6 +1375,12 @@ class InlineQueryLimit(IntEnum):
|
||||
of :class:`int` and can be treated as such.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed deprecated attributes ``InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH`` and
|
||||
``InlineQueryLimit.MAX_SWITCH_PM_TEXT_LENGTH``. Please instead use
|
||||
:attr:`InlineQueryResultsButtonLimit.MIN_START_PARAMETER_LENGTH` and
|
||||
:attr:`InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`.
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
@@ -1389,22 +1395,6 @@ class InlineQueryLimit(IntEnum):
|
||||
MAX_QUERY_LENGTH = 256
|
||||
""":obj:`int`: Maximum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.InlineQuery.query` parameter of :class:`telegram.InlineQuery`."""
|
||||
MIN_SWITCH_PM_TEXT_LENGTH = 1
|
||||
""":obj:`int`: Minimum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.Bot.answer_inline_query.switch_pm_parameter` parameter of
|
||||
:meth:`telegram.Bot.answer_inline_query`.
|
||||
|
||||
.. deprecated:: 20.3
|
||||
Deprecated in favor of :attr:`InlineQueryResultsButtonLimit.MIN_START_PARAMETER_LENGTH`.
|
||||
"""
|
||||
MAX_SWITCH_PM_TEXT_LENGTH = 64
|
||||
""":obj:`int`: Maximum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.Bot.answer_inline_query.switch_pm_parameter` parameter of
|
||||
:meth:`telegram.Bot.answer_inline_query`.
|
||||
|
||||
.. deprecated:: 20.3
|
||||
Deprecated in favor of :attr:`InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`.
|
||||
"""
|
||||
|
||||
|
||||
class InlineQueryResultLimit(IntEnum):
|
||||
@@ -1437,12 +1427,12 @@ class InlineQueryResultsButtonLimit(IntEnum):
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
MIN_START_PARAMETER_LENGTH = InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH
|
||||
MIN_START_PARAMETER_LENGTH = 1
|
||||
""":obj:`int`: Minimum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.InlineQueryResultsButton.start_parameter` parameter of
|
||||
:meth:`telegram.InlineQueryResultsButton`."""
|
||||
|
||||
MAX_START_PARAMETER_LENGTH = InlineQueryLimit.MAX_SWITCH_PM_TEXT_LENGTH
|
||||
MAX_START_PARAMETER_LENGTH = 64
|
||||
""":obj:`int`: Maximum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.InlineQueryResultsButton.start_parameter` parameter of
|
||||
:meth:`telegram.InlineQueryResultsButton`."""
|
||||
|
||||
@@ -741,10 +741,6 @@ class Application(
|
||||
poll_interval: float = 0.0,
|
||||
timeout: int = 10,
|
||||
bootstrap_retries: int = 0,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
allowed_updates: Optional[Sequence[str]] = None,
|
||||
drop_pending_updates: Optional[bool] = None,
|
||||
close_loop: bool = True,
|
||||
@@ -776,6 +772,11 @@ class Application(
|
||||
|
||||
.. include:: inclusions/application_run_tip.rst
|
||||
|
||||
.. versionchanged::
|
||||
Removed the deprecated parameters ``read_timeout``, ``write_timeout``,
|
||||
``connect_timeout``, and ``pool_timeout``. Use the corresponding methods in
|
||||
:class:`telegram.ext.ApplicationBuilder` instead.
|
||||
|
||||
Args:
|
||||
poll_interval (:obj:`float`, optional): Time to wait between polling updates from
|
||||
Telegram in seconds. Default is ``0.0``.
|
||||
@@ -794,38 +795,6 @@ class Application(
|
||||
The default value will be changed to from ``-1`` to ``0``. Indefinite retries
|
||||
during bootstrapping are not recommended.
|
||||
|
||||
read_timeout (:obj:`float`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.read_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. versionchanged:: 20.7
|
||||
Defaults to :attr:`~telegram.request.BaseRequest.DEFAULT_NONE` instead of
|
||||
``2``.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_read_timeout`.
|
||||
write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.write_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_write_timeout`.
|
||||
connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.connect_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_connect_timeout`.
|
||||
pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.pool_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_pool_timeout`.
|
||||
drop_pending_updates (:obj:`bool`, optional): Whether to clean any pending updates on
|
||||
Telegram servers before actually starting to poll. Default is :obj:`False`.
|
||||
allowed_updates (Sequence[:obj:`str`], optional): Passed to
|
||||
@@ -857,16 +826,6 @@ class Application(
|
||||
"Application.run_polling is only available if the application has an Updater."
|
||||
)
|
||||
|
||||
if (read_timeout, write_timeout, connect_timeout, pool_timeout) != ((DEFAULT_NONE,) * 4):
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"Setting timeouts via `Application.run_polling` is deprecated. "
|
||||
"Please use `ApplicationBuilder.get_updates_*_timeout` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
def error_callback(exc: TelegramError) -> None:
|
||||
self.create_task(self.process_error(error=exc, update=None))
|
||||
|
||||
@@ -875,10 +834,6 @@ class Application(
|
||||
poll_interval=poll_interval,
|
||||
timeout=timeout,
|
||||
bootstrap_retries=bootstrap_retries,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
allowed_updates=allowed_updates,
|
||||
drop_pending_updates=drop_pending_updates,
|
||||
error_callback=error_callback, # if there is an error in fetching updates
|
||||
|
||||
@@ -35,7 +35,6 @@ from telegram._utils.types import (
|
||||
ODVInput,
|
||||
SocketOpt,
|
||||
)
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.ext._application import Application
|
||||
from telegram.ext._baseupdateprocessor import BaseUpdateProcessor, SimpleUpdateProcessor
|
||||
from telegram.ext._contexttypes import ContextTypes
|
||||
@@ -45,7 +44,6 @@ from telegram.ext._updater import Updater
|
||||
from telegram.ext._utils.types import BD, BT, CCT, CD, JQ, UD
|
||||
from telegram.request import BaseRequest
|
||||
from telegram.request._httpxrequest import HTTPXRequest
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Update
|
||||
@@ -124,6 +122,9 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
|
||||
.. seealso:: :wiki:`Your First Bot <Extensions---Your-first-Bot>`,
|
||||
:wiki:`Builder Pattern <Builder-Pattern>`
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed deprecated methods ``proxy_url`` and ``get_updates_proxy_url``.
|
||||
|
||||
.. _`builder pattern`: https://en.wikipedia.org/wiki/Builder_pattern
|
||||
"""
|
||||
|
||||
@@ -516,30 +517,6 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
|
||||
self._connection_pool_size = connection_pool_size
|
||||
return self
|
||||
|
||||
def proxy_url(self: BuilderType, proxy_url: str) -> BuilderType:
|
||||
"""Legacy name for :meth:`proxy`, kept for backward compatibility.
|
||||
|
||||
.. seealso:: :meth:`get_updates_proxy`
|
||||
|
||||
.. deprecated:: 20.7
|
||||
|
||||
Args:
|
||||
proxy_url (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``): See
|
||||
:paramref:`telegram.ext.ApplicationBuilder.proxy.proxy`.
|
||||
|
||||
Returns:
|
||||
:class:`ApplicationBuilder`: The same builder with the updated argument.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
"`ApplicationBuilder.proxy_url` is deprecated. Use `ApplicationBuilder.proxy` "
|
||||
"instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.proxy(proxy_url)
|
||||
|
||||
def proxy(self: BuilderType, proxy: Union[str, httpx.Proxy, httpx.URL]) -> BuilderType:
|
||||
"""Sets the proxy for the :paramref:`~telegram.request.HTTPXRequest.proxy`
|
||||
parameter of :attr:`telegram.Bot.request`. Defaults to :obj:`None`.
|
||||
@@ -750,30 +727,6 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
|
||||
self._get_updates_connection_pool_size = get_updates_connection_pool_size
|
||||
return self
|
||||
|
||||
def get_updates_proxy_url(self: BuilderType, get_updates_proxy_url: str) -> BuilderType:
|
||||
"""Legacy name for :meth:`get_updates_proxy`, kept for backward compatibility.
|
||||
|
||||
.. seealso:: :meth:`proxy`
|
||||
|
||||
.. deprecated:: 20.7
|
||||
|
||||
Args:
|
||||
get_updates_proxy_url (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``): See
|
||||
:paramref:`telegram.ext.ApplicationBuilder.get_updates_proxy.get_updates_proxy`.
|
||||
|
||||
Returns:
|
||||
:class:`ApplicationBuilder`: The same builder with the updated argument.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
"`ApplicationBuilder.get_updates_proxy_url` is deprecated. Use "
|
||||
"`ApplicationBuilder.get_updates_proxy` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.get_updates_proxy(get_updates_proxy_url)
|
||||
|
||||
def get_updates_proxy(
|
||||
self: BuilderType, get_updates_proxy: Union[str, httpx.Proxy, httpx.URL]
|
||||
) -> BuilderType:
|
||||
|
||||
+12
-80
@@ -18,14 +18,15 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the class Defaults, which allows passing default values to Application."""
|
||||
import datetime as dtm
|
||||
from typing import Any, NoReturn, Optional, final
|
||||
from typing import TYPE_CHECKING, Any, NoReturn, Optional, final
|
||||
|
||||
from telegram import LinkPreviewOptions
|
||||
from telegram._utils.datetime import UTC
|
||||
from telegram._utils.types import ODVInput
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import LinkPreviewOptions
|
||||
|
||||
|
||||
@final
|
||||
class Defaults:
|
||||
@@ -38,23 +39,15 @@ class Defaults:
|
||||
Removed the argument and attribute ``timeout``. Specify default timeout behavior for the
|
||||
networking backend directly via :class:`telegram.ext.ApplicationBuilder` instead.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed deprecated arguments and properties ``disable_web_page_preview`` and ``quote``.
|
||||
Use :paramref:`link_preview_options` and :paramref:`do_quote` instead.
|
||||
|
||||
Parameters:
|
||||
parse_mode (:obj:`str`, optional): |parse_mode|
|
||||
disable_notification (:obj:`bool`, optional): |disable_notification|
|
||||
disable_web_page_preview (:obj:`bool`, optional): Disables link previews for links in this
|
||||
message. Mutually exclusive with :paramref:`link_preview_options`.
|
||||
|
||||
.. deprecated:: 20.8
|
||||
Use :paramref:`link_preview_options` instead. This parameter will be removed in
|
||||
future versions.
|
||||
|
||||
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|.
|
||||
Will be used for :attr:`telegram.ReplyParameters.allow_sending_without_reply`.
|
||||
quote (:obj:`bool`, optional): |reply_quote|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
Use :paramref:`do_quote` instead. This parameter will be removed in future
|
||||
versions.
|
||||
tzinfo (:class:`datetime.tzinfo`, optional): A timezone to be used for all date(time)
|
||||
inputs appearing throughout PTB, i.e. if a timezone naive date(time) object is passed
|
||||
somewhere, it will be assumed to be in :paramref:`tzinfo`. Defaults to
|
||||
@@ -135,8 +128,6 @@ class Defaults:
|
||||
self,
|
||||
parse_mode: Optional[str] = None,
|
||||
disable_notification: Optional[bool] = None,
|
||||
disable_web_page_preview: Optional[bool] = None,
|
||||
quote: Optional[bool] = None,
|
||||
tzinfo: dtm.tzinfo = UTC,
|
||||
block: bool = True,
|
||||
allow_sending_without_reply: Optional[bool] = None,
|
||||
@@ -164,37 +155,9 @@ class Defaults:
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
if disable_web_page_preview is not None and link_preview_options is not None:
|
||||
raise ValueError(
|
||||
"`disable_web_page_preview` and `link_preview_options` are mutually exclusive."
|
||||
)
|
||||
if quote is not None and do_quote is not None:
|
||||
raise ValueError("`quote` and `do_quote` are mutually exclusive")
|
||||
if disable_web_page_preview is not None:
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.8",
|
||||
"`Defaults.disable_web_page_preview` is deprecated. Use "
|
||||
"`Defaults.link_preview_options` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
self._link_preview_options: Optional[LinkPreviewOptions] = LinkPreviewOptions(
|
||||
is_disabled=disable_web_page_preview
|
||||
)
|
||||
else:
|
||||
self._link_preview_options = link_preview_options
|
||||
self._link_preview_options = link_preview_options
|
||||
self._do_quote = do_quote
|
||||
|
||||
if quote is not None:
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.8", "`Defaults.quote` is deprecated. Use `Defaults.do_quote` instead."
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
self._do_quote: Optional[bool] = quote
|
||||
else:
|
||||
self._do_quote = do_quote
|
||||
# Gather all defaults that actually have a default value
|
||||
self._api_defaults = {}
|
||||
for kwarg in (
|
||||
@@ -223,9 +186,9 @@ class Defaults:
|
||||
(
|
||||
self._parse_mode,
|
||||
self._disable_notification,
|
||||
self.disable_web_page_preview,
|
||||
self._link_preview_options,
|
||||
self._allow_sending_without_reply,
|
||||
self.quote,
|
||||
self._do_quote,
|
||||
self._tzinfo,
|
||||
self._block,
|
||||
self._protect_content,
|
||||
@@ -329,23 +292,6 @@ class Defaults:
|
||||
"You can not assign a new value to disable_notification after initialization."
|
||||
)
|
||||
|
||||
@property
|
||||
def disable_web_page_preview(self) -> ODVInput[bool]:
|
||||
""":obj:`bool`: Optional. Disables link previews for links in all outgoing
|
||||
messages.
|
||||
|
||||
.. deprecated:: 20.8
|
||||
Use :attr:`link_preview_options` instead. This attribute will be removed in future
|
||||
versions.
|
||||
"""
|
||||
return self._link_preview_options.is_disabled if self._link_preview_options else None
|
||||
|
||||
@disable_web_page_preview.setter
|
||||
def disable_web_page_preview(self, _: object) -> NoReturn:
|
||||
raise AttributeError(
|
||||
"You can not assign a new value to disable_web_page_preview after initialization."
|
||||
)
|
||||
|
||||
@property
|
||||
def allow_sending_without_reply(self) -> Optional[bool]:
|
||||
""":obj:`bool`: Optional. Pass :obj:`True`, if the message
|
||||
@@ -359,20 +305,6 @@ class Defaults:
|
||||
"You can not assign a new value to allow_sending_without_reply after initialization."
|
||||
)
|
||||
|
||||
@property
|
||||
def quote(self) -> Optional[bool]:
|
||||
""":obj:`bool`: Optional. |reply_quote|
|
||||
|
||||
.. deprecated:: 20.8
|
||||
Use :attr:`do_quote` instead. This attribute will be removed in future
|
||||
versions.
|
||||
"""
|
||||
return self._do_quote if self._do_quote is not None else None
|
||||
|
||||
@quote.setter
|
||||
def quote(self, _: object) -> NoReturn:
|
||||
raise AttributeError("You can not assign a new value to quote after initialization.")
|
||||
|
||||
@property
|
||||
def tzinfo(self) -> dtm.tzinfo:
|
||||
""":obj:`tzinfo`: A timezone to be used for all date(time) objects appearing
|
||||
|
||||
@@ -26,10 +26,10 @@ from pathlib import Path
|
||||
from types import TracebackType
|
||||
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union
|
||||
|
||||
from telegram._utils.defaultvalue import DEFAULT_80, DEFAULT_IP, DEFAULT_NONE, DefaultValue
|
||||
from telegram._utils.defaultvalue import DEFAULT_80, DEFAULT_IP, DefaultValue
|
||||
from telegram._utils.logging import get_logger
|
||||
from telegram._utils.repr import build_repr_with_selected_attrs
|
||||
from telegram._utils.types import DVType, ODVInput
|
||||
from telegram._utils.types import DVType
|
||||
from telegram.error import TelegramError
|
||||
from telegram.ext._utils.networkloop import network_retry_loop
|
||||
|
||||
@@ -208,10 +208,6 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
poll_interval: float = 0.0,
|
||||
timeout: int = 10,
|
||||
bootstrap_retries: int = 0,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
allowed_updates: Optional[Sequence[str]] = None,
|
||||
drop_pending_updates: Optional[bool] = None,
|
||||
error_callback: Optional[Callable[[TelegramError], None]] = None,
|
||||
@@ -221,6 +217,12 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
.. versionchanged:: 20.0
|
||||
Removed the ``clean`` argument in favor of :paramref:`drop_pending_updates`.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed the deprecated arguments ``read_timeout``, ``write_timeout``,
|
||||
``connect_timeout``, and ``pool_timeout`` in favor of setting the timeouts via
|
||||
the corresponding methods of :class:`telegram.ext.ApplicationBuilder`. or
|
||||
by specifying the timeout via :paramref:`telegram.Bot.get_updates_request`.
|
||||
|
||||
Args:
|
||||
poll_interval (:obj:`float`, optional): Time to wait between polling updates from
|
||||
Telegram in seconds. Default is ``0.0``.
|
||||
@@ -236,41 +238,6 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
.. versionchanged:: 21.11
|
||||
The default value will be changed to from ``-1`` to ``0``. Indefinite retries
|
||||
during bootstrapping are not recommended.
|
||||
read_timeout (:obj:`float`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.read_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. versionchanged:: 20.7
|
||||
Defaults to :attr:`~telegram.request.BaseRequest.DEFAULT_NONE` instead of
|
||||
``2``.
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_read_timeout` or
|
||||
:paramref:`telegram.Bot.get_updates_request`.
|
||||
write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.write_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_write_timeout` or
|
||||
:paramref:`telegram.Bot.get_updates_request`.
|
||||
connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.connect_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_connect_timeout` or
|
||||
:paramref:`telegram.Bot.get_updates_request`.
|
||||
pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
|
||||
:paramref:`telegram.Bot.get_updates.pool_timeout`. Defaults to
|
||||
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
Deprecated in favor of setting the timeout via
|
||||
:meth:`telegram.ext.ApplicationBuilder.get_updates_pool_timeout` or
|
||||
:paramref:`telegram.Bot.get_updates_request`.
|
||||
allowed_updates (Sequence[:obj:`str`], optional): Passed to
|
||||
:meth:`telegram.Bot.get_updates`.
|
||||
|
||||
@@ -324,10 +291,6 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
await self._start_polling(
|
||||
poll_interval=poll_interval,
|
||||
timeout=timeout,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
bootstrap_retries=bootstrap_retries,
|
||||
drop_pending_updates=drop_pending_updates,
|
||||
allowed_updates=allowed_updates,
|
||||
@@ -347,10 +310,6 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
self,
|
||||
poll_interval: float,
|
||||
timeout: int,
|
||||
read_timeout: ODVInput[float],
|
||||
write_timeout: ODVInput[float],
|
||||
connect_timeout: ODVInput[float],
|
||||
pool_timeout: ODVInput[float],
|
||||
bootstrap_retries: int,
|
||||
drop_pending_updates: Optional[bool],
|
||||
allowed_updates: Optional[Sequence[str]],
|
||||
@@ -376,10 +335,6 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
updates = await self.bot.get_updates(
|
||||
offset=self._last_update_id,
|
||||
timeout=timeout,
|
||||
read_timeout=read_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
write_timeout=write_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
allowed_updates=allowed_updates,
|
||||
)
|
||||
except TelegramError:
|
||||
@@ -440,10 +395,6 @@ class Updater(contextlib.AbstractAsyncContextManager["Updater"]):
|
||||
offset=self._last_update_id,
|
||||
# We don't want to do long polling here!
|
||||
timeout=0,
|
||||
read_timeout=read_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
write_timeout=write_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
allowed_updates=allowed_updates,
|
||||
)
|
||||
except TelegramError:
|
||||
|
||||
+6
-39
@@ -34,6 +34,9 @@ This module contains filters for use with :class:`telegram.ext.MessageHandler`,
|
||||
* Filters which do both (like ``Filters.text``) are now split as ready-to-use version
|
||||
``filters.TEXT`` and class version ``filters.Text(...)``.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed deprecated attribute `CHAT`.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
@@ -43,7 +46,6 @@ __all__ = (
|
||||
"AUDIO",
|
||||
"BOOST_ADDED",
|
||||
"CAPTION",
|
||||
"CHAT",
|
||||
"COMMAND",
|
||||
"CONTACT",
|
||||
"EFFECT_ID",
|
||||
@@ -859,21 +861,6 @@ class Chat(_ChatUserBaseFilter):
|
||||
return super()._remove_chat_ids(chat_id)
|
||||
|
||||
|
||||
class _Chat(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.chat)
|
||||
|
||||
|
||||
CHAT = _Chat(name="filters.CHAT")
|
||||
"""This filter filters *any* message that has a :attr:`telegram.Message.chat`.
|
||||
|
||||
.. deprecated:: 20.8
|
||||
This filter has no effect since :attr:`telegram.Message.chat` is always present.
|
||||
"""
|
||||
|
||||
|
||||
class ChatType: # A convenience namespace for Chat types.
|
||||
"""Subset for filtering the type of chat.
|
||||
|
||||
@@ -1915,6 +1902,9 @@ class StatusUpdate:
|
||||
|
||||
Caution:
|
||||
``filters.StatusUpdate`` itself is *not* a filter, but just a convenience namespace.
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed deprecated attribute `USER_SHARED`.
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
@@ -1948,7 +1938,6 @@ class StatusUpdate:
|
||||
or StatusUpdate.PROXIMITY_ALERT_TRIGGERED.check_update(update)
|
||||
or StatusUpdate.REFUNDED_PAYMENT.check_update(update)
|
||||
or StatusUpdate.USERS_SHARED.check_update(update)
|
||||
or StatusUpdate.USER_SHARED.check_update(update)
|
||||
or StatusUpdate.VIDEO_CHAT_ENDED.check_update(update)
|
||||
or StatusUpdate.VIDEO_CHAT_PARTICIPANTS_INVITED.check_update(update)
|
||||
or StatusUpdate.VIDEO_CHAT_SCHEDULED.check_update(update)
|
||||
@@ -2204,28 +2193,6 @@ class StatusUpdate:
|
||||
.. versionadded:: 21.4
|
||||
"""
|
||||
|
||||
class _UserShared(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.api_kwargs.get("user_shared"))
|
||||
|
||||
USER_SHARED = _UserShared(name="filters.StatusUpdate.USER_SHARED")
|
||||
"""Messages that contain ``"user_shared"`` in :attr:`telegram.TelegramObject.api_kwargs`.
|
||||
|
||||
Warning:
|
||||
This will only catch the legacy ``user_shared`` field, not the
|
||||
new :attr:`telegram.Message.users_shared` attribute!
|
||||
|
||||
.. versionchanged:: 21.0
|
||||
Now relies on :attr:`telegram.TelegramObject.api_kwargs` as the native attribute
|
||||
``Message.user_shared`` was removed.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
.. deprecated:: 20.8
|
||||
Use :attr:`USERS_SHARED` instead.
|
||||
"""
|
||||
|
||||
class _UsersShared(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ from telegram._utils.defaultvalue import DefaultValue
|
||||
from telegram._utils.logging import get_logger
|
||||
from telegram._utils.strings import TextEncoding
|
||||
from telegram._utils.types import JSONDict, ODVInput
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram._version import __version__ as ptb_ver
|
||||
from telegram.error import (
|
||||
BadRequest,
|
||||
@@ -42,7 +41,6 @@ from telegram.error import (
|
||||
TelegramError,
|
||||
)
|
||||
from telegram.request._requestdata import RequestData
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
RT = TypeVar("RT", bound="BaseRequest")
|
||||
|
||||
@@ -133,22 +131,19 @@ class BaseRequest(
|
||||
await self.shutdown()
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def read_timeout(self) -> Optional[float]:
|
||||
"""This property must return the default read timeout in seconds used by this class.
|
||||
More precisely, the returned value should be the one used when
|
||||
:paramref:`post.read_timeout` of :meth:post` is not passed/equal to :attr:`DEFAULT_NONE`.
|
||||
|
||||
.. versionadded:: 20.7
|
||||
|
||||
Warning:
|
||||
For now this property does not need to be implemented by subclasses and will raise
|
||||
:exc:`NotImplementedError` if accessed without being overridden. However, in future
|
||||
versions, this property will be abstract and must be implemented by subclasses.
|
||||
.. versionchanged:: 22.0
|
||||
This property is now required to be implemented by subclasses.
|
||||
|
||||
Returns:
|
||||
:obj:`float` | :obj:`None`: The read timeout in seconds.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def initialize(self) -> None:
|
||||
@@ -305,31 +300,6 @@ class BaseRequest(
|
||||
TelegramError
|
||||
|
||||
"""
|
||||
# Import needs to be here since HTTPXRequest is a subclass of BaseRequest
|
||||
from telegram.request import HTTPXRequest # pylint: disable=import-outside-toplevel
|
||||
|
||||
# 20 is the documented default value for all the media related bot methods and custom
|
||||
# implementations of BaseRequest may explicitly rely on that. Hence, we follow the
|
||||
# standard deprecation policy and deprecate starting with version 20.7.
|
||||
# For our own implementation HTTPXRequest, we can handle that ourselves, so we skip the
|
||||
# warning in that case.
|
||||
has_files = request_data and request_data.multipart_data
|
||||
if (
|
||||
has_files
|
||||
and not isinstance(self, HTTPXRequest)
|
||||
and isinstance(write_timeout, DefaultValue)
|
||||
):
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
f"The `write_timeout` parameter passed to {self.__class__.__name__}.do_request"
|
||||
" will default to `BaseRequest.DEFAULT_NONE` instead of 20 in future versions "
|
||||
"for *all* methods of the `Bot` class, including methods sending media.",
|
||||
),
|
||||
stacklevel=3,
|
||||
)
|
||||
write_timeout = 20
|
||||
|
||||
try:
|
||||
code, payload = await self.do_request(
|
||||
url=url,
|
||||
|
||||
@@ -25,11 +25,9 @@ import httpx
|
||||
from telegram._utils.defaultvalue import DefaultValue
|
||||
from telegram._utils.logging import get_logger
|
||||
from telegram._utils.types import HTTPVersion, ODVInput, SocketOpt
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.error import NetworkError, TimedOut
|
||||
from telegram.request._baserequest import BaseRequest
|
||||
from telegram.request._requestdata import RequestData
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
# Note to future devs:
|
||||
# Proxies are currently only tested manually. The httpx development docs have a nice guide on that:
|
||||
@@ -45,6 +43,9 @@ class HTTPXRequest(BaseRequest):
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
.. versionchanged:: 22.0
|
||||
Removed the deprecated parameter ``proxy_url``. Use :paramref:`proxy` instead.
|
||||
|
||||
Args:
|
||||
connection_pool_size (:obj:`int`, optional): Number of connections to keep in the
|
||||
connection pool. Defaults to ``1``.
|
||||
@@ -52,10 +53,6 @@ class HTTPXRequest(BaseRequest):
|
||||
Note:
|
||||
Independent of the value, one additional connection will be reserved for
|
||||
:meth:`telegram.Bot.get_updates`.
|
||||
proxy_url (:obj:`str`, optional): Legacy name for :paramref:`proxy`, kept for backward
|
||||
compatibility. Defaults to :obj:`None`.
|
||||
|
||||
.. deprecated:: 20.7
|
||||
read_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum
|
||||
amount of time (in seconds) to wait for a response from Telegram's server.
|
||||
This value is used unless a different value is passed to :meth:`do_request`.
|
||||
@@ -145,7 +142,6 @@ class HTTPXRequest(BaseRequest):
|
||||
def __init__(
|
||||
self,
|
||||
connection_pool_size: int = 1,
|
||||
proxy_url: Optional[Union[str, httpx.Proxy, httpx.URL]] = None,
|
||||
read_timeout: Optional[float] = 5.0,
|
||||
write_timeout: Optional[float] = 5.0,
|
||||
connect_timeout: Optional[float] = 5.0,
|
||||
@@ -156,18 +152,6 @@ class HTTPXRequest(BaseRequest):
|
||||
media_write_timeout: Optional[float] = 20.0,
|
||||
httpx_kwargs: Optional[dict[str, Any]] = None,
|
||||
):
|
||||
if proxy_url is not None and proxy is not None:
|
||||
raise ValueError("The parameters `proxy_url` and `proxy` are mutually exclusive.")
|
||||
|
||||
if proxy_url is not None:
|
||||
proxy = proxy_url
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"20.7", "The parameter `proxy_url` is deprecated. Use `proxy` instead."
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
self._http_version = http_version
|
||||
self._media_write_timeout = media_write_timeout
|
||||
timeout = httpx.Timeout(
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
import pytest
|
||||
|
||||
from telegram import PassportElementErrorFiles, PassportElementErrorSelfie
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from tests.auxil.slots import mro_slots
|
||||
|
||||
|
||||
@@ -49,8 +48,8 @@ class TestPassportElementErrorFilesWithoutRequest(PassportElementErrorFilesTestB
|
||||
def test_expected_values(self, passport_element_error_files):
|
||||
assert passport_element_error_files.source == self.source
|
||||
assert passport_element_error_files.type == self.type_
|
||||
assert isinstance(passport_element_error_files.file_hashes, list)
|
||||
assert passport_element_error_files.file_hashes == self.file_hashes
|
||||
assert isinstance(passport_element_error_files.file_hashes, tuple)
|
||||
assert passport_element_error_files.file_hashes == tuple(self.file_hashes)
|
||||
assert passport_element_error_files.message == self.message
|
||||
|
||||
def test_to_dict(self, passport_element_error_files):
|
||||
@@ -60,9 +59,8 @@ class TestPassportElementErrorFilesWithoutRequest(PassportElementErrorFilesTestB
|
||||
assert passport_element_error_files_dict["source"] == passport_element_error_files.source
|
||||
assert passport_element_error_files_dict["type"] == passport_element_error_files.type
|
||||
assert passport_element_error_files_dict["message"] == passport_element_error_files.message
|
||||
assert (
|
||||
passport_element_error_files_dict["file_hashes"]
|
||||
== passport_element_error_files.file_hashes
|
||||
assert passport_element_error_files_dict["file_hashes"] == list(
|
||||
passport_element_error_files.file_hashes
|
||||
)
|
||||
|
||||
def test_equality(self):
|
||||
@@ -88,13 +86,3 @@ class TestPassportElementErrorFilesWithoutRequest(PassportElementErrorFilesTestB
|
||||
|
||||
assert a != f
|
||||
assert hash(a) != hash(f)
|
||||
|
||||
def test_file_hashes_deprecated(self, passport_element_error_files, recwarn):
|
||||
passport_element_error_files.file_hashes
|
||||
assert len(recwarn) == 1
|
||||
assert (
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions." in str(recwarn[0].message)
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
import pytest
|
||||
|
||||
from telegram import PassportElementErrorSelfie, PassportElementErrorTranslationFiles
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from tests.auxil.slots import mro_slots
|
||||
|
||||
|
||||
@@ -51,8 +50,8 @@ class TestPassportElementErrorTranslationFilesWithoutRequest(
|
||||
def test_expected_values(self, passport_element_error_translation_files):
|
||||
assert passport_element_error_translation_files.source == self.source
|
||||
assert passport_element_error_translation_files.type == self.type_
|
||||
assert isinstance(passport_element_error_translation_files.file_hashes, list)
|
||||
assert passport_element_error_translation_files.file_hashes == self.file_hashes
|
||||
assert isinstance(passport_element_error_translation_files.file_hashes, tuple)
|
||||
assert passport_element_error_translation_files.file_hashes == tuple(self.file_hashes)
|
||||
assert passport_element_error_translation_files.message == self.message
|
||||
|
||||
def test_to_dict(self, passport_element_error_translation_files):
|
||||
@@ -73,9 +72,8 @@ class TestPassportElementErrorTranslationFilesWithoutRequest(
|
||||
passport_element_error_translation_files_dict["message"]
|
||||
== passport_element_error_translation_files.message
|
||||
)
|
||||
assert (
|
||||
passport_element_error_translation_files_dict["file_hashes"]
|
||||
== passport_element_error_translation_files.file_hashes
|
||||
assert passport_element_error_translation_files_dict["file_hashes"] == list(
|
||||
passport_element_error_translation_files.file_hashes
|
||||
)
|
||||
|
||||
def test_equality(self):
|
||||
@@ -101,13 +99,3 @@ class TestPassportElementErrorTranslationFilesWithoutRequest(
|
||||
|
||||
assert a != f
|
||||
assert hash(a) != hash(f)
|
||||
|
||||
def test_file_hashes_deprecated(self, passport_element_error_translation_files, recwarn):
|
||||
passport_element_error_translation_files.file_hashes
|
||||
assert len(recwarn) == 1
|
||||
assert (
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions." in str(recwarn[0].message)
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import datetime as dtm
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import Bot, File, PassportElementError, PassportFile
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from telegram._utils.datetime import UTC, to_timestamp
|
||||
from tests.auxil.bot_method_checks import (
|
||||
check_defaults_handling,
|
||||
check_shortcut_call,
|
||||
@@ -44,7 +46,7 @@ class PassportFileTestBase:
|
||||
file_id = "data"
|
||||
file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
file_size = 50
|
||||
file_date = 1532879128
|
||||
file_date = dtm.datetime.now(tz=UTC).replace(microsecond=0)
|
||||
|
||||
|
||||
class TestPassportFileWithoutRequest(PassportFileTestBase):
|
||||
@@ -67,7 +69,27 @@ class TestPassportFileWithoutRequest(PassportFileTestBase):
|
||||
assert passport_file_dict["file_id"] == passport_file.file_id
|
||||
assert passport_file_dict["file_unique_id"] == passport_file.file_unique_id
|
||||
assert passport_file_dict["file_size"] == passport_file.file_size
|
||||
assert passport_file_dict["file_date"] == passport_file.file_date
|
||||
assert passport_file_dict["file_date"] == to_timestamp(passport_file.file_date)
|
||||
|
||||
def test_de_json_localization(self, passport_file, tz_bot, offline_bot, raw_bot):
|
||||
json_dict = {
|
||||
"file_id": self.file_id,
|
||||
"file_unique_id": self.file_unique_id,
|
||||
"file_size": self.file_size,
|
||||
"file_date": to_timestamp(self.file_date),
|
||||
}
|
||||
|
||||
pf = PassportFile.de_json(json_dict, offline_bot)
|
||||
pf_raw = PassportFile.de_json(json_dict, raw_bot)
|
||||
pf_tz = PassportFile.de_json(json_dict, tz_bot)
|
||||
|
||||
# comparing utcoffsets because comparing timezones is unpredicatable
|
||||
date_offset = pf_tz.file_date.utcoffset()
|
||||
tz_bot_offset = tz_bot.defaults.tzinfo.utcoffset(pf_tz.file_date.replace(tzinfo=None))
|
||||
|
||||
assert pf_raw.file_date.tzinfo == UTC
|
||||
assert pf.file_date.tzinfo == UTC
|
||||
assert date_offset == tz_bot_offset
|
||||
|
||||
def test_equality(self):
|
||||
a = PassportFile(self.file_id, self.file_unique_id, self.file_size, self.file_date)
|
||||
@@ -89,16 +111,6 @@ class TestPassportFileWithoutRequest(PassportFileTestBase):
|
||||
assert a != e
|
||||
assert hash(a) != hash(e)
|
||||
|
||||
def test_file_date_deprecated(self, passport_file, recwarn):
|
||||
passport_file.file_date
|
||||
assert len(recwarn) == 1
|
||||
assert (
|
||||
"The attribute `file_date` will return a datetime instead of an integer in future"
|
||||
" major versions." in str(recwarn[0].message)
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__
|
||||
|
||||
async def test_get_file_instance_method(self, monkeypatch, passport_file):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
result = kwargs["file_id"] == passport_file.file_id
|
||||
|
||||
@@ -619,8 +619,6 @@ async def check_defaults_handling(
|
||||
defaults_no_custom_defaults = Defaults()
|
||||
kwargs = {kwarg: "custom_default" for kwarg in inspect.signature(Defaults).parameters}
|
||||
kwargs["tzinfo"] = zoneinfo.ZoneInfo("America/New_York")
|
||||
kwargs.pop("disable_web_page_preview") # mutually exclusive with link_preview_options
|
||||
kwargs.pop("quote") # mutually exclusive with do_quote
|
||||
kwargs["link_preview_options"] = LinkPreviewOptions(
|
||||
url="custom_default", show_above_text="custom_default"
|
||||
)
|
||||
|
||||
@@ -71,6 +71,10 @@ class OfflineRequest(BaseRequest):
|
||||
async def shutdown(self) -> None:
|
||||
pass
|
||||
|
||||
@property
|
||||
def read_timeout(self):
|
||||
return 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
@@ -1516,49 +1516,6 @@ class TestApplication:
|
||||
found_log = True
|
||||
assert found_log
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"timeout_name",
|
||||
["read_timeout", "connect_timeout", "write_timeout", "pool_timeout", "poll_interval"],
|
||||
)
|
||||
@pytest.mark.skipif(
|
||||
platform.system() == "Windows",
|
||||
reason="Can't send signals without stopping whole process on windows",
|
||||
)
|
||||
def test_run_polling_timeout_deprecation_warnings(
|
||||
self, timeout_name, monkeypatch, recwarn, app
|
||||
):
|
||||
def thread_target():
|
||||
waited = 0
|
||||
while not app.running:
|
||||
time.sleep(0.05)
|
||||
waited += 0.05
|
||||
if waited > 5:
|
||||
pytest.fail("App apparently won't start")
|
||||
|
||||
time.sleep(0.05)
|
||||
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
|
||||
monkeypatch.setattr(app.bot, "get_updates", empty_get_updates)
|
||||
|
||||
thread = Thread(target=thread_target)
|
||||
thread.start()
|
||||
|
||||
kwargs = {timeout_name: 42}
|
||||
app.run_polling(drop_pending_updates=True, close_loop=False, **kwargs)
|
||||
thread.join()
|
||||
|
||||
if timeout_name == "poll_interval":
|
||||
assert len(recwarn) == 0
|
||||
return
|
||||
|
||||
assert len(recwarn) == 1
|
||||
assert "Setting timeouts via `Application.run_polling` is deprecated." in str(
|
||||
recwarn[0].message
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__, "wrong stacklevel"
|
||||
|
||||
@pytest.mark.skipif(
|
||||
platform.system() == "Windows",
|
||||
reason="Can't send signals without stopping whole process on windows",
|
||||
|
||||
@@ -41,7 +41,6 @@ from telegram.ext import (
|
||||
from telegram.ext._applicationbuilder import _BOT_CHECKS
|
||||
from telegram.ext._baseupdateprocessor import SimpleUpdateProcessor
|
||||
from telegram.request import HTTPXRequest
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from tests.auxil.constants import PRIVATE_KEY
|
||||
from tests.auxil.envvars import TEST_WITH_OPT_DEPS
|
||||
from tests.auxil.files import data_file
|
||||
@@ -207,7 +206,6 @@ class TestApplicationBuilder:
|
||||
"write_timeout",
|
||||
"media_write_timeout",
|
||||
"proxy",
|
||||
"proxy_url",
|
||||
"socket_options",
|
||||
"bot",
|
||||
"updater",
|
||||
@@ -217,9 +215,8 @@ class TestApplicationBuilder:
|
||||
def test_mutually_exclusive_for_request(self, builder, method):
|
||||
builder.request(1)
|
||||
|
||||
method_name = method.replace("proxy_url", "proxy")
|
||||
with pytest.raises(
|
||||
RuntimeError, match=f"`{method_name}` may only be set, if no request instance"
|
||||
RuntimeError, match=f"`{method}` may only be set, if no request instance"
|
||||
):
|
||||
getattr(builder, method)(data_file("private.key"))
|
||||
|
||||
@@ -237,7 +234,6 @@ class TestApplicationBuilder:
|
||||
"get_updates_read_timeout",
|
||||
"get_updates_write_timeout",
|
||||
"get_updates_proxy",
|
||||
"get_updates_proxy_url",
|
||||
"get_updates_socket_options",
|
||||
"get_updates_http_version",
|
||||
"bot",
|
||||
@@ -247,10 +243,9 @@ class TestApplicationBuilder:
|
||||
def test_mutually_exclusive_for_get_updates_request(self, builder, method):
|
||||
builder.get_updates_request(1)
|
||||
|
||||
method_name = method.replace("proxy_url", "proxy")
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match=f"`{method_name}` may only be set, if no get_updates_request instance",
|
||||
match=f"`{method}` may only be set, if no get_updates_request instance",
|
||||
):
|
||||
getattr(builder, method)(data_file("private.key"))
|
||||
|
||||
@@ -267,7 +262,6 @@ class TestApplicationBuilder:
|
||||
"get_updates_pool_timeout",
|
||||
"get_updates_read_timeout",
|
||||
"get_updates_write_timeout",
|
||||
"get_updates_proxy_url",
|
||||
"get_updates_proxy",
|
||||
"get_updates_socket_options",
|
||||
"get_updates_http_version",
|
||||
@@ -278,7 +272,6 @@ class TestApplicationBuilder:
|
||||
"write_timeout",
|
||||
"media_write_timeout",
|
||||
"proxy",
|
||||
"proxy_url",
|
||||
"socket_options",
|
||||
"http_version",
|
||||
"bot",
|
||||
@@ -290,17 +283,15 @@ class TestApplicationBuilder:
|
||||
def test_mutually_exclusive_for_updater(self, builder, method):
|
||||
builder.updater(1)
|
||||
|
||||
method_name = method.replace("proxy_url", "proxy")
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match=f"`{method_name}` may only be set, if no updater",
|
||||
match=f"`{method}` may only be set, if no updater",
|
||||
):
|
||||
getattr(builder, method)(data_file("private.key"))
|
||||
|
||||
builder = ApplicationBuilder()
|
||||
getattr(builder, method)(data_file("private.key"))
|
||||
|
||||
method = method.replace("proxy_url", "proxy")
|
||||
with pytest.raises(RuntimeError, match=f"`updater` may only be set, if no {method}"):
|
||||
builder.updater(1)
|
||||
|
||||
@@ -313,7 +304,6 @@ class TestApplicationBuilder:
|
||||
"get_updates_read_timeout",
|
||||
"get_updates_write_timeout",
|
||||
"get_updates_proxy",
|
||||
"get_updates_proxy_url",
|
||||
"get_updates_socket_options",
|
||||
"get_updates_http_version",
|
||||
"connection_pool_size",
|
||||
@@ -323,7 +313,6 @@ class TestApplicationBuilder:
|
||||
"write_timeout",
|
||||
"media_write_timeout",
|
||||
"proxy",
|
||||
"proxy_url",
|
||||
"socket_options",
|
||||
"bot",
|
||||
"http_version",
|
||||
@@ -341,14 +330,11 @@ class TestApplicationBuilder:
|
||||
getattr(builder, method)(data_file("private.key"))
|
||||
builder.updater(None)
|
||||
|
||||
# We test with bot the new & legacy version to ensure that the legacy version still works
|
||||
@pytest.mark.parametrize(
|
||||
("proxy_method", "get_updates_proxy_method"),
|
||||
[("proxy", "get_updates_proxy"), ("proxy_url", "get_updates_proxy_url")],
|
||||
ids=["new", "legacy"],
|
||||
)
|
||||
def test_all_bot_args_custom(
|
||||
self, builder, bot, monkeypatch, proxy_method, get_updates_proxy_method
|
||||
self,
|
||||
builder,
|
||||
bot,
|
||||
monkeypatch,
|
||||
):
|
||||
# Only socket_options is tested in a standalone test, since that's easier
|
||||
defaults = Defaults()
|
||||
@@ -403,8 +389,7 @@ class TestApplicationBuilder:
|
||||
builder = ApplicationBuilder().token(bot.token)
|
||||
builder.connection_pool_size(1).connect_timeout(2).pool_timeout(3).read_timeout(
|
||||
4
|
||||
).write_timeout(5).media_write_timeout(6).http_version("1.1")
|
||||
getattr(builder, proxy_method)("proxy")
|
||||
).write_timeout(5).media_write_timeout(6).http_version("1.1").proxy("proxy")
|
||||
app = builder.build()
|
||||
client = app.bot.request._client
|
||||
|
||||
@@ -423,8 +408,9 @@ class TestApplicationBuilder:
|
||||
5
|
||||
).get_updates_http_version(
|
||||
"1.1"
|
||||
).get_updates_proxy(
|
||||
"get_updates_proxy"
|
||||
)
|
||||
getattr(builder, get_updates_proxy_method)("get_updates_proxy")
|
||||
app = builder.build()
|
||||
client = app.bot._request[0]._client
|
||||
|
||||
@@ -585,22 +571,6 @@ class TestApplicationBuilder:
|
||||
assert isinstance(app.update_queue, asyncio.Queue)
|
||||
assert isinstance(app.updater, Updater)
|
||||
|
||||
def test_proxy_url_deprecation_warning(self, bot, builder, recwarn):
|
||||
builder.token(bot.token).proxy_url("proxy_url")
|
||||
assert len(recwarn) == 1
|
||||
assert "`ApplicationBuilder.proxy_url` is deprecated" in str(recwarn[0].message)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__, "wrong stacklevel"
|
||||
|
||||
def test_get_updates_proxy_url_deprecation_warning(self, bot, builder, recwarn):
|
||||
builder.token(bot.token).get_updates_proxy_url("get_updates_proxy_url")
|
||||
assert len(recwarn) == 1
|
||||
assert "`ApplicationBuilder.get_updates_proxy_url` is deprecated" in str(
|
||||
recwarn[0].message
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__, "wrong stacklevel"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("read_timeout", "timeout", "expected"),
|
||||
[
|
||||
|
||||
@@ -22,7 +22,7 @@ import inspect
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import LinkPreviewOptions, User
|
||||
from telegram import User
|
||||
from telegram.ext import Defaults
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from tests.auxil.envvars import TEST_WITH_OPT_DEPS
|
||||
@@ -31,7 +31,7 @@ from tests.auxil.slots import mro_slots
|
||||
|
||||
class TestDefaults:
|
||||
def test_slot_behaviour(self):
|
||||
a = Defaults(parse_mode="HTML", quote=True)
|
||||
a = Defaults(parse_mode="HTML", do_quote=True)
|
||||
for attr in a.__slots__:
|
||||
assert getattr(a, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
assert len(mro_slots(a)) == len(set(mro_slots(a))), "duplicate slot"
|
||||
@@ -63,8 +63,8 @@ class TestDefaults:
|
||||
c = Defaults(parse_mode="HTML", do_quote=True, protect_content=True)
|
||||
d = Defaults(parse_mode="HTML", protect_content=True)
|
||||
e = User(123, "test_user", False)
|
||||
f = Defaults(parse_mode="HTML", disable_web_page_preview=True)
|
||||
g = Defaults(parse_mode="HTML", disable_web_page_preview=True)
|
||||
f = Defaults(parse_mode="HTML", block=True)
|
||||
g = Defaults(parse_mode="HTML", block=True)
|
||||
|
||||
assert a == b
|
||||
assert hash(a) == hash(b)
|
||||
@@ -81,29 +81,3 @@ class TestDefaults:
|
||||
|
||||
assert f == g
|
||||
assert hash(f) == hash(g)
|
||||
|
||||
def test_mutually_exclusive(self):
|
||||
with pytest.raises(ValueError, match="mutually exclusive"):
|
||||
Defaults(disable_web_page_preview=True, link_preview_options=LinkPreviewOptions(False))
|
||||
with pytest.raises(ValueError, match="mutually exclusive"):
|
||||
Defaults(quote=True, do_quote=False)
|
||||
|
||||
def test_deprecation_warning_for_disable_web_page_preview(self):
|
||||
with pytest.warns(
|
||||
PTBDeprecationWarning, match="`Defaults.disable_web_page_preview` is "
|
||||
) as record:
|
||||
Defaults(disable_web_page_preview=True)
|
||||
|
||||
assert record[0].filename == __file__, "wrong stacklevel!"
|
||||
|
||||
assert Defaults(disable_web_page_preview=True).link_preview_options.is_disabled is True
|
||||
assert Defaults(disable_web_page_preview=False).disable_web_page_preview is False
|
||||
|
||||
def test_deprecation_warning_for_quote(self):
|
||||
with pytest.warns(PTBDeprecationWarning, match="`Defaults.quote` is ") as record:
|
||||
Defaults(quote=True)
|
||||
|
||||
assert record[0].filename == __file__, "wrong stacklevel!"
|
||||
|
||||
assert Defaults(quote=True).do_quote is True
|
||||
assert Defaults(quote=False).quote is False
|
||||
|
||||
@@ -1068,11 +1068,6 @@ class TestFilters:
|
||||
assert filters.StatusUpdate.WRITE_ACCESS_ALLOWED.check_update(update)
|
||||
update.message.write_access_allowed = None
|
||||
|
||||
update.message.api_kwargs = {"user_shared": "user_shared"}
|
||||
assert filters.StatusUpdate.ALL.check_update(update)
|
||||
assert filters.StatusUpdate.USER_SHARED.check_update(update)
|
||||
update.message.api_kwargs = {}
|
||||
|
||||
update.message.users_shared = "users_shared"
|
||||
assert filters.StatusUpdate.ALL.check_update(update)
|
||||
assert filters.StatusUpdate.USERS_SHARED.check_update(update)
|
||||
@@ -1334,15 +1329,12 @@ class TestFilters:
|
||||
|
||||
def test_filters_chat_id(self, update):
|
||||
assert not filters.Chat(chat_id=1).check_update(update)
|
||||
assert filters.CHAT.check_update(update)
|
||||
update.message.chat.id = 1
|
||||
assert filters.Chat(chat_id=1).check_update(update)
|
||||
assert filters.CHAT.check_update(update)
|
||||
update.message.chat.id = 2
|
||||
assert filters.Chat(chat_id=[1, 2]).check_update(update)
|
||||
assert not filters.Chat(chat_id=[3, 4]).check_update(update)
|
||||
update.message.chat = None
|
||||
assert not filters.CHAT.check_update(update)
|
||||
assert not filters.Chat(chat_id=[3, 4]).check_update(update)
|
||||
|
||||
def test_filters_chat_username(self, update):
|
||||
|
||||
@@ -85,6 +85,10 @@ class TestBaseRateLimiter:
|
||||
async def shutdown(self) -> None:
|
||||
pass
|
||||
|
||||
@property
|
||||
def read_timeout(self):
|
||||
return 1
|
||||
|
||||
async def do_request(self, *args, **kwargs):
|
||||
if TestBaseRateLimiter.request_received is None:
|
||||
TestBaseRateLimiter.request_received = []
|
||||
@@ -163,6 +167,10 @@ class TestAIORateLimiter:
|
||||
async def shutdown(self) -> None:
|
||||
pass
|
||||
|
||||
@property
|
||||
def read_timeout(self):
|
||||
return 1
|
||||
|
||||
async def do_request(self, *args, **kwargs):
|
||||
request_data = kwargs.get("request_data")
|
||||
allow_paid_broadcast = request_data.parameters.get("allow_paid_broadcast", False)
|
||||
|
||||
@@ -27,7 +27,6 @@ from random import randrange
|
||||
import pytest
|
||||
|
||||
from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram.error import InvalidToken, RetryAfter, TelegramError, TimedOut
|
||||
from telegram.ext import ExtBot, InvalidCallbackData, Updater
|
||||
from tests.auxil.build_messages import make_message, make_message_update
|
||||
@@ -296,10 +295,6 @@ class TestUpdater:
|
||||
received_kwargs = {}
|
||||
expected_kwargs = {
|
||||
"timeout": 0,
|
||||
"read_timeout": "read_timeout",
|
||||
"connect_timeout": "connect_timeout",
|
||||
"write_timeout": "write_timeout",
|
||||
"pool_timeout": "pool_timeout",
|
||||
"allowed_updates": "allowed_updates",
|
||||
}
|
||||
|
||||
@@ -422,10 +417,6 @@ class TestUpdater:
|
||||
|
||||
expected = {
|
||||
"timeout": 10,
|
||||
"read_timeout": DEFAULT_NONE,
|
||||
"write_timeout": DEFAULT_NONE,
|
||||
"connect_timeout": DEFAULT_NONE,
|
||||
"pool_timeout": DEFAULT_NONE,
|
||||
"allowed_updates": None,
|
||||
"api_kwargs": None,
|
||||
}
|
||||
@@ -466,10 +457,6 @@ class TestUpdater:
|
||||
|
||||
expected = {
|
||||
"timeout": 42,
|
||||
"read_timeout": 43,
|
||||
"write_timeout": 44,
|
||||
"connect_timeout": 45,
|
||||
"pool_timeout": 46,
|
||||
"allowed_updates": ["message"],
|
||||
"api_kwargs": None,
|
||||
}
|
||||
@@ -477,10 +464,6 @@ class TestUpdater:
|
||||
await update_queue.put(Update(update_id=2))
|
||||
await updater.start_polling(
|
||||
timeout=42,
|
||||
read_timeout=43,
|
||||
write_timeout=44,
|
||||
connect_timeout=45,
|
||||
pool_timeout=46,
|
||||
allowed_updates=["message"],
|
||||
)
|
||||
await update_queue.join()
|
||||
|
||||
+11
-100
@@ -45,10 +45,9 @@ from telegram.error import (
|
||||
TelegramError,
|
||||
TimedOut,
|
||||
)
|
||||
from telegram.request import BaseRequest, RequestData
|
||||
from telegram.request import RequestData
|
||||
from telegram.request._httpxrequest import HTTPXRequest
|
||||
from telegram.request._requestparameter import RequestParameter
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from tests.auxil.envvars import TEST_WITH_OPT_DEPS
|
||||
from tests.auxil.files import data_file
|
||||
from tests.auxil.networking import NonchalantHttpxRequest
|
||||
@@ -390,76 +389,6 @@ class TestRequestWithoutRequest:
|
||||
)
|
||||
assert self.test_flag == (1, 2, 3, 4)
|
||||
|
||||
def test_read_timeout_not_implemented(self):
|
||||
class SimpleRequest(BaseRequest):
|
||||
async def do_request(self, *args, **kwargs):
|
||||
raise httpx.ReadTimeout("read timeout")
|
||||
|
||||
async def initialize(self) -> None:
|
||||
pass
|
||||
|
||||
async def shutdown(self) -> None:
|
||||
pass
|
||||
|
||||
with pytest.raises(NotImplementedError):
|
||||
SimpleRequest().read_timeout
|
||||
|
||||
@pytest.mark.parametrize("media", [True, False])
|
||||
async def test_timeout_propagation_write_timeout(
|
||||
self, monkeypatch, media, input_media_photo, recwarn # noqa: F811
|
||||
):
|
||||
class CustomRequest(BaseRequest):
|
||||
async def initialize(self_) -> None:
|
||||
pass
|
||||
|
||||
async def shutdown(self_) -> None:
|
||||
pass
|
||||
|
||||
async def do_request(self_, *args, **kwargs) -> tuple[int, bytes]:
|
||||
self.test_flag = (
|
||||
kwargs.get("read_timeout"),
|
||||
kwargs.get("connect_timeout"),
|
||||
kwargs.get("write_timeout"),
|
||||
kwargs.get("pool_timeout"),
|
||||
)
|
||||
return HTTPStatus.OK, b'{"ok": "True", "result": {}}'
|
||||
|
||||
custom_request = CustomRequest()
|
||||
data = {"string": "string", "int": 1, "float": 1.0}
|
||||
if media:
|
||||
data["media"] = input_media_photo
|
||||
request_data = RequestData(
|
||||
parameters=[RequestParameter.from_input(key, value) for key, value in data.items()],
|
||||
)
|
||||
|
||||
# First make sure that custom timeouts are always respected
|
||||
await custom_request.post(
|
||||
"url", request_data, read_timeout=1, connect_timeout=2, write_timeout=3, pool_timeout=4
|
||||
)
|
||||
assert self.test_flag == (1, 2, 3, 4)
|
||||
|
||||
# Now also ensure that the default timeout for media requests is 20 seconds
|
||||
await custom_request.post("url", request_data)
|
||||
assert self.test_flag == (
|
||||
DEFAULT_NONE,
|
||||
DEFAULT_NONE,
|
||||
20 if media else DEFAULT_NONE,
|
||||
DEFAULT_NONE,
|
||||
)
|
||||
|
||||
print("warnings")
|
||||
for entry in recwarn:
|
||||
print(entry.message)
|
||||
if media:
|
||||
assert len(recwarn) == 1
|
||||
assert "will default to `BaseRequest.DEFAULT_NONE` instead of 20" in str(
|
||||
recwarn[0].message
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__
|
||||
else:
|
||||
assert len(recwarn) == 0
|
||||
|
||||
|
||||
@pytest.mark.skipif(not TEST_WITH_OPT_DEPS, reason="No need to run this twice")
|
||||
class TestHTTPXRequestWithoutRequest:
|
||||
@@ -469,9 +398,7 @@ class TestHTTPXRequestWithoutRequest:
|
||||
def _reset(self):
|
||||
self.test_flag = None
|
||||
|
||||
# We parametrize this to make sure that the legacy `proxy_url` argument is still supported
|
||||
@pytest.mark.parametrize("proxy_argument", ["proxy", "proxy_url"])
|
||||
def test_init(self, monkeypatch, proxy_argument):
|
||||
def test_init(self, monkeypatch):
|
||||
@dataclass
|
||||
class Client:
|
||||
timeout: object
|
||||
@@ -492,32 +419,20 @@ class TestHTTPXRequestWithoutRequest:
|
||||
assert request._client.http1 is True
|
||||
assert not request._client.http2
|
||||
|
||||
kwargs = {
|
||||
"connection_pool_size": 42,
|
||||
proxy_argument: "proxy",
|
||||
"connect_timeout": 43,
|
||||
"read_timeout": 44,
|
||||
"write_timeout": 45,
|
||||
"pool_timeout": 46,
|
||||
}
|
||||
request = HTTPXRequest(**kwargs)
|
||||
request = HTTPXRequest(
|
||||
connection_pool_size=42,
|
||||
proxy="proxy",
|
||||
connect_timeout=43,
|
||||
read_timeout=44,
|
||||
write_timeout=45,
|
||||
pool_timeout=46,
|
||||
)
|
||||
assert request._client.proxy == "proxy"
|
||||
assert request._client.limits == httpx.Limits(
|
||||
max_connections=42, max_keepalive_connections=42
|
||||
)
|
||||
assert request._client.timeout == httpx.Timeout(connect=43, read=44, write=45, pool=46)
|
||||
|
||||
def test_proxy_mutually_exclusive(self):
|
||||
with pytest.raises(ValueError, match="mutually exclusive"):
|
||||
HTTPXRequest(proxy="proxy", proxy_url="proxy_url")
|
||||
|
||||
def test_proxy_url_deprecation_warning(self, recwarn):
|
||||
HTTPXRequest(proxy_url="http://127.0.0.1:3128")
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert "`proxy_url` is deprecated" in str(recwarn[0].message)
|
||||
assert recwarn[0].filename == __file__, "incorrect stacklevel"
|
||||
|
||||
async def test_multiple_inits_and_shutdowns(self, monkeypatch):
|
||||
self.test_flag = defaultdict(int)
|
||||
|
||||
@@ -728,7 +643,7 @@ class TestHTTPXRequestWithoutRequest:
|
||||
|
||||
@pytest.mark.parametrize("media", [True, False])
|
||||
async def test_do_request_write_timeout(
|
||||
self, monkeypatch, media, httpx_request, input_media_photo, recwarn # noqa: F811
|
||||
self, monkeypatch, media, httpx_request, input_media_photo # noqa: F811
|
||||
):
|
||||
async def request(_, **kwargs):
|
||||
self.test_flag = kwargs.get("timeout")
|
||||
@@ -753,10 +668,6 @@ class TestHTTPXRequestWithoutRequest:
|
||||
await httpx_request.post("url", request_data)
|
||||
assert self.test_flag == httpx.Timeout(read=5, connect=5, write=20 if media else 5, pool=1)
|
||||
|
||||
# Just for double-checking, since warnings are issued for implementations of BaseRequest
|
||||
# other than HTTPXRequest
|
||||
assert len(recwarn) == 0
|
||||
|
||||
@pytest.mark.parametrize("init", [True, False])
|
||||
async def test_setting_media_write_timeout(
|
||||
self, monkeypatch, init, input_media_photo, recwarn # noqa: F811
|
||||
|
||||
+9
-35
@@ -95,7 +95,7 @@ from telegram.error import BadRequest, EndPointNotFound, InvalidToken
|
||||
from telegram.ext import ExtBot, InvalidCallbackData
|
||||
from telegram.helpers import escape_markdown
|
||||
from telegram.request import BaseRequest, HTTPXRequest, RequestData
|
||||
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
|
||||
from telegram.warnings import PTBUserWarning
|
||||
from tests.auxil.bot_method_checks import check_defaults_handling
|
||||
from tests.auxil.ci_bots import FALLBACKS
|
||||
from tests.auxil.envvars import GITHUB_ACTIONS
|
||||
@@ -681,7 +681,7 @@ class TestBotWithoutRequest:
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"default_bot",
|
||||
[{"parse_mode": "Markdown", "disable_web_page_preview": True}],
|
||||
[{"parse_mode": "Markdown", "link_preview_options": LinkPreviewOptions(is_disabled=True)}],
|
||||
indirect=True,
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
@@ -976,7 +976,7 @@ class TestBotWithoutRequest:
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"default_bot",
|
||||
[{"parse_mode": "Markdown", "disable_web_page_preview": True}],
|
||||
[{"parse_mode": "Markdown", "link_preview_options": LinkPreviewOptions(is_disabled=True)}],
|
||||
indirect=True,
|
||||
)
|
||||
async def test_answer_inline_query_default_parse_mode(self, monkeypatch, default_bot):
|
||||
@@ -2257,6 +2257,10 @@ class TestBotWithoutRequest:
|
||||
)
|
||||
return HTTPStatus.OK, b'{"ok": "True", "result": {}}'
|
||||
|
||||
@property
|
||||
def read_timeout(self):
|
||||
return 1
|
||||
|
||||
custom_request = CustomRequest()
|
||||
|
||||
offline_bot = Bot(offline_bot.token, request=custom_request)
|
||||
@@ -2271,7 +2275,7 @@ class TestBotWithoutRequest:
|
||||
assert test_flag == (
|
||||
DEFAULT_NONE,
|
||||
DEFAULT_NONE,
|
||||
20,
|
||||
DEFAULT_NONE,
|
||||
DEFAULT_NONE,
|
||||
)
|
||||
|
||||
@@ -3221,36 +3225,6 @@ class TestBotWithRequest:
|
||||
if updates:
|
||||
assert isinstance(updates[0], Update)
|
||||
|
||||
@pytest.mark.parametrize("bot_class", [Bot, ExtBot])
|
||||
async def test_get_updates_read_timeout_deprecation_warning(
|
||||
self, bot, recwarn, monkeypatch, bot_class
|
||||
):
|
||||
# Using the normal HTTPXRequest should not issue any warnings
|
||||
await bot.get_updates()
|
||||
assert len(recwarn) == 0
|
||||
|
||||
# Now let's test deprecation warning when using get_updates for other BaseRequest
|
||||
# subclasses (we just monkeypatch the existing HTTPXRequest for this)
|
||||
read_timeout = None
|
||||
|
||||
async def catch_timeouts(*args, **kwargs):
|
||||
nonlocal read_timeout
|
||||
read_timeout = kwargs.get("read_timeout")
|
||||
return HTTPStatus.OK, b'{"ok": "True", "result": {}}'
|
||||
|
||||
monkeypatch.setattr(HTTPXRequest, "read_timeout", BaseRequest.read_timeout)
|
||||
monkeypatch.setattr(HTTPXRequest, "do_request", catch_timeouts)
|
||||
|
||||
bot = bot_class(get_updates_request=HTTPXRequest(), token=bot.token)
|
||||
await bot.get_updates()
|
||||
|
||||
assert len(recwarn) == 1
|
||||
assert "does not override the property `read_timeout`" in str(recwarn[0].message)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
assert recwarn[0].filename == __file__, "wrong stacklevel"
|
||||
|
||||
assert read_timeout == 2
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("read_timeout", "timeout", "expected"),
|
||||
[
|
||||
@@ -4211,7 +4185,7 @@ class TestBotWithRequest:
|
||||
]
|
||||
)
|
||||
await poll_message.stop_poll(reply_markup=reply_markup)
|
||||
helper_message = await poll_message.reply_text("temp", quote=True)
|
||||
helper_message = await poll_message.reply_text("temp", do_quote=True)
|
||||
message = helper_message.reply_to_message
|
||||
inline_keyboard = message.reply_markup.inline_keyboard
|
||||
|
||||
|
||||
+29
-45
@@ -17,7 +17,6 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
import contextlib
|
||||
import datetime as dtm
|
||||
from copy import copy
|
||||
|
||||
@@ -448,18 +447,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
async def check_quote_parsing(
|
||||
message: Message, method, bot_method_name: str, args, monkeypatch
|
||||
):
|
||||
"""Used in testing reply_* below. Makes sure that quote and do_quote are handled
|
||||
correctly
|
||||
"""
|
||||
with contextlib.suppress(TypeError):
|
||||
# for newer methods that don't have the deprecated argument
|
||||
with pytest.raises(ValueError, match="`quote` and `do_quote` are mutually exclusive"):
|
||||
await method(*args, quote=True, do_quote=True)
|
||||
|
||||
# for newer methods that don't have the deprecated argument
|
||||
with pytest.warns(PTBDeprecationWarning, match="`quote` parameter is deprecated"):
|
||||
await method(*args, quote=True)
|
||||
|
||||
"""Used in testing reply_* below. Makes sure that do_quote is handled correctly"""
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="`reply_to_message_id` and `reply_parameters` are mutually exclusive.",
|
||||
@@ -471,17 +459,13 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
|
||||
monkeypatch.setattr(message.get_bot(), bot_method_name, make_assertion)
|
||||
|
||||
for param in ("quote", "do_quote"):
|
||||
with contextlib.suppress(TypeError):
|
||||
# for newer methods that don't have the deprecated argument
|
||||
chat_id, reply_parameters = await method(*args, **{param: True})
|
||||
if chat_id != message.chat.id:
|
||||
pytest.fail(f"chat_id is {chat_id} but should be {message.chat.id}")
|
||||
if reply_parameters is None or reply_parameters.message_id != message.message_id:
|
||||
pytest.fail(
|
||||
f"reply_parameters is {reply_parameters} "
|
||||
"but should be {message.message_id}"
|
||||
)
|
||||
for value in (True, False):
|
||||
chat_id, reply_parameters = await method(*args, do_quote=value)
|
||||
if chat_id != message.chat.id:
|
||||
pytest.fail(f"chat_id is {chat_id} but should be {message.chat.id}")
|
||||
expected = ReplyParameters(message.message_id) if value else None
|
||||
if reply_parameters != expected:
|
||||
pytest.fail(f"reply_parameters is {reply_parameters} but should be {expected}")
|
||||
|
||||
input_chat_id = object()
|
||||
input_reply_parameters = ReplyParameters(message_id=1, chat_id=42)
|
||||
@@ -1451,7 +1435,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_text,
|
||||
Bot.send_message,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1493,7 +1477,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_markdown,
|
||||
Bot.send_message,
|
||||
["chat_id", "parse_mode", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1542,7 +1526,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_markdown_v2,
|
||||
Bot.send_message,
|
||||
["chat_id", "parse_mode", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1594,7 +1578,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_html,
|
||||
Bot.send_message,
|
||||
["chat_id", "parse_mode", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1631,7 +1615,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_media_group,
|
||||
Bot.send_media_group,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1673,7 +1657,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_photo,
|
||||
Bot.send_photo,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1707,7 +1691,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_audio,
|
||||
Bot.send_audio,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1741,7 +1725,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_document,
|
||||
Bot.send_document,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1775,7 +1759,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_animation,
|
||||
Bot.send_animation,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1809,7 +1793,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_sticker,
|
||||
Bot.send_sticker,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1843,7 +1827,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_video,
|
||||
Bot.send_video,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1877,7 +1861,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_video_note,
|
||||
Bot.send_video_note,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1911,7 +1895,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_voice,
|
||||
Bot.send_voice,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1945,7 +1929,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_location,
|
||||
Bot.send_location,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -1979,7 +1963,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_venue,
|
||||
Bot.send_venue,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -2013,7 +1997,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_contact,
|
||||
Bot.send_contact,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -2048,7 +2032,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_poll,
|
||||
Bot.send_poll,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -2082,7 +2066,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_dice,
|
||||
Bot.send_dice,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -2154,7 +2138,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_game,
|
||||
Bot.send_game,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -2197,7 +2181,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_invoice,
|
||||
Bot.send_invoice,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
@@ -2326,7 +2310,7 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
Message.reply_copy,
|
||||
Bot.copy_message,
|
||||
["chat_id", "reply_to_message_id", "business_connection_id"],
|
||||
["quote", "do_quote", "reply_to_message_id"],
|
||||
["do_quote", "reply_to_message_id"],
|
||||
annotation_overrides={"message_thread_id": (ODVInput[int], DEFAULT_NONE)},
|
||||
)
|
||||
assert await check_shortcut_call(message.copy, message.get_bot(), "copy_message")
|
||||
|
||||
@@ -190,8 +190,6 @@ def check_param_type(
|
||||
or "Unix time" in tg_parameter.param_description
|
||||
):
|
||||
log("Checking that `%s` is a datetime!\n", ptb_param.name)
|
||||
if ptb_param.name in PTCE.DATETIME_EXCEPTIONS:
|
||||
return True, mapped_type
|
||||
# If it's a class, we only accept datetime as the parameter
|
||||
mapped_type = dtm.datetime if is_class else mapped_type | dtm.datetime
|
||||
|
||||
|
||||
@@ -73,8 +73,6 @@ class ParamTypeCheckingExceptions:
|
||||
("keyboard", True): "KeyboardButton", # + sequence[sequence[str]]
|
||||
("reaction", False): "ReactionType", # + str
|
||||
("options", False): "InputPollOption", # + str
|
||||
# TODO: Deprecated and will be corrected (and removed) in next bot api release
|
||||
("file_hashes", True): "list[str]",
|
||||
}
|
||||
|
||||
# Special cases for other parameters that accept more types than the official API, and are
|
||||
@@ -117,11 +115,6 @@ class ParamTypeCheckingExceptions:
|
||||
# These classes' params are all ODVInput, so we ignore them in the defaults type checking.
|
||||
IGNORED_DEFAULTS_CLASSES = {"LinkPreviewOptions"}
|
||||
|
||||
# TODO: Remove this in v22 when it becomes a datetime (also remove from arg_type_checker.py)
|
||||
DATETIME_EXCEPTIONS = {
|
||||
"file_date",
|
||||
}
|
||||
|
||||
|
||||
# Arguments *added* to the official API
|
||||
PTB_EXTRA_PARAMS = {
|
||||
|
||||
@@ -138,6 +138,11 @@ def test_check_object(tg_class: TelegramClass) -> None:
|
||||
- No unexpected parameters
|
||||
"""
|
||||
obj = getattr(telegram, tg_class.class_name)
|
||||
if tg_class.class_name not in (
|
||||
"PassportElementErrorFiles",
|
||||
"PassportElementErrorTranslationFiles",
|
||||
):
|
||||
return
|
||||
|
||||
# Check arguments based on source. Makes sure to only check __init__'s signature & nothing else
|
||||
sig = inspect.signature(obj.__init__, follow_wrapped=True)
|
||||
|
||||
Reference in New Issue
Block a user