mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2025-01-04 18:12:12 +01:00
Merge branch 'master' into admonition-overhaul
This commit is contained in:
commit
f47df21dbf
160 changed files with 2064 additions and 1289 deletions
2
.github/workflows/docs-linkcheck.yml
vendored
2
.github/workflows/docs-linkcheck.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.9]
|
python-version: [3.10]
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
fail-fast: False
|
fail-fast: False
|
||||||
steps:
|
steps:
|
||||||
|
|
107
.github/workflows/release_pypi.yml
vendored
107
.github/workflows/release_pypi.yml
vendored
|
@ -1,17 +1,15 @@
|
||||||
name: Publish to PyPI
|
name: Publish to PyPI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# Run on any tag
|
# manually trigger the workflow
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '**'
|
|
||||||
# manually trigger the workflow - for testing only
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build Distribution
|
name: Build Distribution
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
TAG: ${{ steps.get_tag.outputs.TAG }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -29,11 +27,15 @@ jobs:
|
||||||
with:
|
with:
|
||||||
name: python-package-distributions
|
name: python-package-distributions
|
||||||
path: dist/
|
path: dist/
|
||||||
|
- name: Get Tag Name
|
||||||
|
id: get_tag
|
||||||
|
run: |
|
||||||
|
pip install .
|
||||||
|
TAG=$(python -c "from telegram import __version__; print(f'v{__version__}')")
|
||||||
|
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
publish-to-pypi:
|
publish-to-pypi:
|
||||||
name: Publish to PyPI
|
name: Publish to PyPI
|
||||||
# only publish to PyPI on tag pushes
|
|
||||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
|
||||||
needs:
|
needs:
|
||||||
- build
|
- build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -52,42 +54,11 @@ jobs:
|
||||||
- name: Publish to PyPI
|
- name: Publish to PyPI
|
||||||
uses: pypa/gh-action-pypi-publish@release/v1
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
|
||||||
publish-to-test-pypi:
|
|
||||||
name: Publish to Test PyPI
|
|
||||||
needs:
|
|
||||||
- build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment:
|
|
||||||
name: release_test_pypi
|
|
||||||
url: https://test.pypi.org/p/python-telegram-bot
|
|
||||||
permissions:
|
|
||||||
id-token: write # IMPORTANT: mandatory for trusted publishing
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download all the dists
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: python-package-distributions
|
|
||||||
path: dist/
|
|
||||||
- name: Publish to Test PyPI
|
|
||||||
uses: pypa/gh-action-pypi-publish@release/v1
|
|
||||||
with:
|
|
||||||
repository-url: https://test.pypi.org/legacy/
|
|
||||||
|
|
||||||
compute-signatures:
|
compute-signatures:
|
||||||
name: Compute SHA1 Sums and Sign with Sigstore
|
name: Compute SHA1 Sums and Sign with Sigstore
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- publish-to-pypi
|
- publish-to-pypi
|
||||||
- publish-to-test-pypi
|
|
||||||
# run if either of the publishing jobs ran successfully
|
|
||||||
# see also:
|
|
||||||
# https://github.com/actions/runner/issues/491#issuecomment-850884422
|
|
||||||
if: |
|
|
||||||
always() && (
|
|
||||||
(needs.publish-to-pypi.result == 'success') ||
|
|
||||||
(needs.publish-to-test-pypi.result == 'success')
|
|
||||||
)
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write # IMPORTANT: mandatory for sigstore
|
id-token: write # IMPORTANT: mandatory for sigstore
|
||||||
|
@ -106,7 +77,7 @@ jobs:
|
||||||
sha1sum $file > $file.sha1
|
sha1sum $file > $file.sha1
|
||||||
done
|
done
|
||||||
- name: Sign the dists with Sigstore
|
- name: Sign the dists with Sigstore
|
||||||
uses: sigstore/gh-action-sigstore-python@v2.1.1
|
uses: sigstore/gh-action-sigstore-python@v3.0.0
|
||||||
with:
|
with:
|
||||||
inputs: >-
|
inputs: >-
|
||||||
./dist/*.tar.gz
|
./dist/*.tar.gz
|
||||||
|
@ -120,13 +91,8 @@ jobs:
|
||||||
github-release:
|
github-release:
|
||||||
name: Upload to GitHub Release
|
name: Upload to GitHub Release
|
||||||
needs:
|
needs:
|
||||||
- publish-to-pypi
|
- build
|
||||||
- compute-signatures
|
- compute-signatures
|
||||||
if: |
|
|
||||||
always() && (
|
|
||||||
(needs.publish-to-pypi.result == 'success') &&
|
|
||||||
(needs.compute-signatures.result == 'success')
|
|
||||||
)
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
@ -142,63 +108,22 @@ jobs:
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
# Create a GitHub Release for this tag. The description can be changed later, as for now
|
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.
|
# we don't define it through this workflow.
|
||||||
run: >-
|
run: >-
|
||||||
gh release create
|
gh release create
|
||||||
'${{ github.ref_name }}'
|
'${{ env.TAG }}'
|
||||||
--repo '${{ github.repository }}'
|
--repo '${{ github.repository }}'
|
||||||
--generate-notes
|
--generate-notes
|
||||||
- name: Upload artifact signatures to GitHub Release
|
- name: Upload artifact signatures to GitHub Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
TAG: ${{ needs.build.outputs.TAG }}
|
||||||
# Upload to GitHub Release using the `gh` CLI.
|
# Upload to GitHub Release using the `gh` CLI.
|
||||||
# `dist/` contains the built packages, and the
|
# `dist/` contains the built packages, and the
|
||||||
# sigstore-produced signatures and certificates.
|
# sigstore-produced signatures and certificates.
|
||||||
run: >-
|
run: >-
|
||||||
gh release upload
|
gh release upload
|
||||||
'${{ github.ref_name }}' dist/**
|
'${{ env.TAG }}' dist/**
|
||||||
--repo '${{ github.repository }}'
|
|
||||||
|
|
||||||
github-test-release:
|
|
||||||
name: Upload to GitHub Release Draft
|
|
||||||
needs:
|
|
||||||
- publish-to-test-pypi
|
|
||||||
- compute-signatures
|
|
||||||
if: |
|
|
||||||
always() && (
|
|
||||||
(needs.publish-to-test-pypi.result == 'success') &&
|
|
||||||
(needs.compute-signatures.result == 'success')
|
|
||||||
)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write # IMPORTANT: mandatory for making GitHub Releases
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download all the dists
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: python-package-distributions-and-signatures
|
|
||||||
path: dist/
|
|
||||||
- name: Create GitHub Release
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
# Create a GitHub Release *draft*. The description can be changed later, as for now
|
|
||||||
# we don't define it through this workflow.
|
|
||||||
run: >-
|
|
||||||
gh release create
|
|
||||||
'${{ github.ref_name }}'
|
|
||||||
--repo '${{ github.repository }}'
|
|
||||||
--generate-notes
|
|
||||||
--draft
|
|
||||||
- name: Upload artifact signatures to GitHub Release
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
# Upload to GitHub Release using the `gh` CLI.
|
|
||||||
# `dist/` contains the built packages, and the
|
|
||||||
# sigstore-produced signatures and certificates.
|
|
||||||
run: >-
|
|
||||||
gh release upload
|
|
||||||
'${{ github.ref_name }}' dist/**
|
|
||||||
--repo '${{ github.repository }}'
|
--repo '${{ github.repository }}'
|
||||||
|
|
132
.github/workflows/release_test_pypi.yml
vendored
Normal file
132
.github/workflows/release_test_pypi.yml
vendored
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
name: Publish to Test PyPI
|
||||||
|
|
||||||
|
on:
|
||||||
|
# manually trigger the workflow
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build Distribution
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
TAG: ${{ steps.get_tag.outputs.TAG }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
- name: Install pypa/build
|
||||||
|
run: >-
|
||||||
|
python3 -m pip install build --user
|
||||||
|
- name: Build a binary wheel and a source tarball
|
||||||
|
run: python3 -m build
|
||||||
|
- name: Store the distribution packages
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: python-package-distributions
|
||||||
|
path: dist/
|
||||||
|
- name: Get Tag Name
|
||||||
|
id: get_tag
|
||||||
|
run: |
|
||||||
|
pip install .
|
||||||
|
TAG=$(python -c "from telegram import __version__; print(f'v{__version__}')")
|
||||||
|
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
publish-to-test-pypi:
|
||||||
|
name: Publish to Test PyPI
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: release_test_pypi
|
||||||
|
url: https://test.pypi.org/p/python-telegram-bot
|
||||||
|
permissions:
|
||||||
|
id-token: write # IMPORTANT: mandatory for trusted publishing
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download all the dists
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: python-package-distributions
|
||||||
|
path: dist/
|
||||||
|
- name: Publish to Test PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
repository-url: https://test.pypi.org/legacy/
|
||||||
|
|
||||||
|
compute-signatures:
|
||||||
|
name: Compute SHA1 Sums and Sign with Sigstore
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- publish-to-test-pypi
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write # IMPORTANT: mandatory for sigstore
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download all the dists
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: python-package-distributions
|
||||||
|
path: dist/
|
||||||
|
- name: Compute SHA1 Sums
|
||||||
|
run: |
|
||||||
|
# Compute SHA1 sum of the distribution packages and save it to a file with the same name,
|
||||||
|
# but with .sha1 extension
|
||||||
|
for file in dist/*; do
|
||||||
|
sha1sum $file > $file.sha1
|
||||||
|
done
|
||||||
|
- name: Sign the dists with Sigstore
|
||||||
|
uses: sigstore/gh-action-sigstore-python@v3.0.0
|
||||||
|
with:
|
||||||
|
inputs: >-
|
||||||
|
./dist/*.tar.gz
|
||||||
|
./dist/*.whl
|
||||||
|
- name: Store the distribution packages and signatures
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: python-package-distributions-and-signatures
|
||||||
|
path: dist/
|
||||||
|
|
||||||
|
github-test-release:
|
||||||
|
name: Upload to GitHub Release Draft
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
- compute-signatures
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write # IMPORTANT: mandatory for making GitHub Releases
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download all the dists
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: python-package-distributions-and-signatures
|
||||||
|
path: dist/
|
||||||
|
- name: Create GitHub Release
|
||||||
|
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.
|
||||||
|
run: >-
|
||||||
|
gh release create
|
||||||
|
'${{ env.TAG }}'
|
||||||
|
--repo '${{ github.repository }}'
|
||||||
|
--generate-notes
|
||||||
|
--draft
|
||||||
|
- name: Upload artifact signatures to GitHub Release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
TAG: ${{ needs.build.outputs.TAG }}
|
||||||
|
# Upload to GitHub Release using the `gh` CLI.
|
||||||
|
# `dist/` contains the built packages, and the
|
||||||
|
# sigstore-produced signatures and certificates.
|
||||||
|
run: >-
|
||||||
|
gh release upload
|
||||||
|
'${{ env.TAG }}' dist/**
|
||||||
|
--repo '${{ github.repository }}'
|
52
CHANGES.rst
52
CHANGES.rst
|
@ -4,6 +4,58 @@
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
Version 21.5
|
||||||
|
============
|
||||||
|
|
||||||
|
*Released 2024-09-01*
|
||||||
|
|
||||||
|
This is the technical changelog for version 21.5. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
|
||||||
|
|
||||||
|
Major Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Full Support for Bot API 7.9 (:pr:`4429`)
|
||||||
|
- Full Support for Bot API 7.8 (:pr:`4408`)
|
||||||
|
|
||||||
|
New Features
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Add ``MessageEntity.shift_entities`` and ``MessageEntity.concatenate`` (:pr:`4376` closes :issue:`4372`)
|
||||||
|
- Add Parameter ``game_pattern`` to ``CallbackQueryHandler`` (:pr:`4353` by `jainamoswal <https://github.com/jainamoswal>`_ closes :issue:`4269`)
|
||||||
|
- Add Parameter ``read_file_handle`` to ``InputFile`` (:pr:`4388` closes :issue:`4339`)
|
||||||
|
|
||||||
|
Documentation Improvements
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
- Bugfix for "Available In" Admonitions (:pr:`4413`)
|
||||||
|
- Documentation Improvements (:pr:`4400` closes :issue:`4446`, :pr:`4448` by `Palaptin <https://github.com/Palaptin>`_)
|
||||||
|
- Document Return Types of ``RequestData`` Members (:pr:`4396`)
|
||||||
|
- Add Introductory Paragraphs to Telegram Types Subsections (:pr:`4389` by `mohdyusuf2312 <https://github.com/mohdyusuf2312>`_ closes :issue:`4380`)
|
||||||
|
- Start Adapting to RTD Addons (:pr:`4386`)
|
||||||
|
|
||||||
|
Minor and Internal Changes
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
- Remove Surplus Logging from ``Updater`` Network Loop (:pr:`4432` by `MartinHjelmare <https://github.com/MartinHjelmare>`_)
|
||||||
|
- Add Internal Constants for Encodings (:pr:`4378` by `elpekenin <https://github.com/elpekenin>`_)
|
||||||
|
- Improve PyPI Automation (:pr:`4375` closes :issue:`4373`)
|
||||||
|
- Update Test Suite to New Test Channel Setup (:pr:`4435`)
|
||||||
|
- Improve Fixture Usage in ``test_message.py`` (:pr:`4431` by `Palaptin <https://github.com/Palaptin>`_)
|
||||||
|
- Update Python 3.13 Test Suite to RC1 (:pr:`4415`)
|
||||||
|
- Bump ``ruff`` and Add New Rules (:pr:`4416`)
|
||||||
|
|
||||||
|
Dependency Updates
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Update ``cachetools`` requirement from <5.5.0,>=5.3.3 to >=5.3.3,<5.6.0 (:pr:`4437`)
|
||||||
|
- Bump ``sphinx`` from 7.4.7 to 8.0.2 and ``furo`` from 2024.7.18 to 2024.8.6 (:pr:`4412`)
|
||||||
|
- Bump ``test-summary/action`` from 2.3 to 2.4 (:pr:`4410`)
|
||||||
|
- Bump ``pytest`` from 8.2.2 to 8.3.2 (:pr:`4403`)
|
||||||
|
- Bump ``dependabot/fetch-metadata`` from 2.1.0 to 2.2.0 (:pr:`4411`)
|
||||||
|
- Update ``cachetools`` requirement from ~=5.3.3 to >=5.3.3,<5.5.0 (:pr:`4390`)
|
||||||
|
- Bump ``sphinx`` from 7.3.7 to 7.4.7 (:pr:`4395`)
|
||||||
|
- Bump ``furo`` from 2024.5.6 to 2024.7.18 (:pr:`4392`)
|
||||||
|
|
||||||
Version 21.4
|
Version 21.4
|
||||||
============
|
============
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
:target: https://pypi.org/project/python-telegram-bot/
|
:target: https://pypi.org/project/python-telegram-bot/
|
||||||
:alt: Supported Python versions
|
:alt: Supported Python versions
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/Bot%20API-7.8-blue?logo=telegram
|
.. image:: https://img.shields.io/badge/Bot%20API-7.9-blue?logo=telegram
|
||||||
:target: https://core.telegram.org/bots/api-changelog
|
:target: https://core.telegram.org/bots/api-changelog
|
||||||
:alt: Supported Bot API version
|
:alt: Supported Bot API version
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ After installing_ the library, be sure to check out the section on `working with
|
||||||
Telegram API support
|
Telegram API support
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
All types and methods of the Telegram Bot API **7.8** are natively supported by this library.
|
All types and methods of the Telegram Bot API **7.9** are natively supported by this library.
|
||||||
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
|
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
|
||||||
|
|
||||||
Notable Features
|
Notable Features
|
||||||
|
@ -119,7 +119,7 @@ Verifying Releases
|
||||||
|
|
||||||
To enable you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team, we have taken the following measures.
|
To enable you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team, we have taken the following measures.
|
||||||
|
|
||||||
Starting with v21.4, all releases are signed via `sigstore <https://sigstore.dev>`_.
|
Starting with v21.4, all releases are signed via `sigstore <https://www.sigstore.dev>`_.
|
||||||
The corresponding signature files are uploaded to the `GitHub releases page`_.
|
The corresponding signature files are uploaded to the `GitHub releases page`_.
|
||||||
To verify the signature, please install the `sigstore Python client <https://pypi.org/project/sigstore/>`_ and follow the instructions for `verifying signatures from GitHub Actions <https://github.com/sigstore/sigstore-python#signatures-from-github-actions>`_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``.
|
To verify the signature, please install the `sigstore Python client <https://pypi.org/project/sigstore/>`_ and follow the instructions for `verifying signatures from GitHub Actions <https://github.com/sigstore/sigstore-python#signatures-from-github-actions>`_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``.
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ PTB can be installed with optional dependencies:
|
||||||
* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
||||||
* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1.0 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
|
* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1.0 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
|
||||||
* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.4 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
|
* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.4 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
|
||||||
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools>=5.3.3,<5.5.0 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
|
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools>=5.3.3,<5.6.0 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
|
||||||
* ``pip install "python-telegram-bot[job-queue]"`` installs the `APScheduler~=3.10.4 <https://apscheduler.readthedocs.io/en/3.x/>`_ library and enforces `pytz>=2018.6 <https://pypi.org/project/pytz/>`_, where ``pytz`` is a dependency of ``APScheduler``. Use this, if you want to use the ``telegram.ext.JobQueue``.
|
* ``pip install "python-telegram-bot[job-queue]"`` installs the `APScheduler~=3.10.4 <https://apscheduler.readthedocs.io/en/3.x/>`_ library and enforces `pytz>=2018.6 <https://pypi.org/project/pytz/>`_, where ``pytz`` is a dependency of ``APScheduler``. Use this, if you want to use the ``telegram.ext.JobQueue``.
|
||||||
|
|
||||||
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot[socks,webhooks]"``.
|
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot[socks,webhooks]"``.
|
||||||
|
|
|
@ -130,6 +130,7 @@ Available Types
|
||||||
telegram.reactiontype
|
telegram.reactiontype
|
||||||
telegram.reactiontypecustomemoji
|
telegram.reactiontypecustomemoji
|
||||||
telegram.reactiontypeemoji
|
telegram.reactiontypeemoji
|
||||||
|
telegram.reactiontypepaid
|
||||||
telegram.replykeyboardmarkup
|
telegram.replykeyboardmarkup
|
||||||
telegram.replykeyboardremove
|
telegram.replykeyboardremove
|
||||||
telegram.replyparameters
|
telegram.replyparameters
|
||||||
|
|
|
@ -10,7 +10,7 @@ Your bot can offer users **HTML5 games** to play solo or to compete against each
|
||||||
* If you send the game message without any buttons, it will automatically have a 'Play ``GameName``' button. When this button is pressed, your bot gets a :class:`telegram.CallbackQuery` with the ``game_short_name`` of the requested game. You provide the correct URL for this particular user and the app opens the game in the in-app browser.
|
* If you send the game message without any buttons, it will automatically have a 'Play ``GameName``' button. When this button is pressed, your bot gets a :class:`telegram.CallbackQuery` with the ``game_short_name`` of the requested game. You provide the correct URL for this particular user and the app opens the game in the in-app browser.
|
||||||
* You can manually add multiple buttons to your game message. Please note that the first button in the first row **must always** launch the game, using the field ``callback_game`` in :class:`telegram.InlineKeyboardButton`. You can add extra buttons according to taste: e.g., for a description of the rules, or to open the game's official community.
|
* You can manually add multiple buttons to your game message. Please note that the first button in the first row **must always** launch the game, using the field ``callback_game`` in :class:`telegram.InlineKeyboardButton`. You can add extra buttons according to taste: e.g., for a description of the rules, or to open the game's official community.
|
||||||
* To make your game more attractive, you can upload a GIF animation that demonstrates the game to the users via `BotFather <https://t.me/botfather>`_ (see `Lumberjack <https://t.me/gamebot?game=lumberjack>`_ for example).
|
* To make your game more attractive, you can upload a GIF animation that demonstrates the game to the users via `BotFather <https://t.me/botfather>`_ (see `Lumberjack <https://t.me/gamebot?game=lumberjack>`_ for example).
|
||||||
* A game message will also display high scores for the current chat. Use :meth:`~telegram.Bot.setGameScore` to post high scores to the chat with the game, optionally add the :paramref:`~telegram.Bot.set_game_score.disable_edit_message` parameter if you don't want to automatically update the message with the current scoreboard.
|
* A game message will also display high scores for the current chat. Use :meth:`~telegram.Bot.setGameScore` to post high scores to the chat with the game, add the :paramref:`~telegram.Bot.set_game_score.disable_edit_message` parameter to disable automatic update of the message with the current scoreboard.
|
||||||
* Use :meth:`~telegram.Bot.getGameHighScores` to get data for in-game high score tables.
|
* Use :meth:`~telegram.Bot.getGameHighScores` to get data for in-game high score tables.
|
||||||
* You can also add an extra sharing button for users to share their best score to different chats.
|
* You can also add an extra sharing button for users to share their best score to different chats.
|
||||||
* For examples of what can be done using this new stuff, check the `@gamebot <https://t.me/gamebot>`_ and `@gamee <https://t.me/gamee>`_ bots.
|
* For examples of what can be done using this new stuff, check the `@gamebot <https://t.me/gamebot>`_ and `@gamee <https://t.me/gamee>`_ bots.
|
||||||
|
|
6
docs/source/telegram.reactiontypepaid.rst
Normal file
6
docs/source/telegram.reactiontypepaid.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
ReactionTypePaid
|
||||||
|
================
|
||||||
|
|
||||||
|
.. autoclass:: telegram.ReactionTypePaid
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
|
@ -60,10 +60,12 @@
|
||||||
|
|
||||||
.. |removed_thumb_note| replace:: Removed the deprecated argument and attribute ``thumb``.
|
.. |removed_thumb_note| replace:: Removed the deprecated argument and attribute ``thumb``.
|
||||||
|
|
||||||
.. |removed_thumb_url_note| replace:: Removed the deprecated argument and attribute ``thumb_url``.
|
.. |removed_thumb_url_note| replace:: Removed the deprecated argument and attribute ``thumb_url`` which made thumbnail_url mandatory.
|
||||||
|
|
||||||
.. |removed_thumb_wildcard_note| replace:: Removed the deprecated arguments and attributes ``thumb_*``.
|
.. |removed_thumb_wildcard_note| replace:: Removed the deprecated arguments and attributes ``thumb_*``.
|
||||||
|
|
||||||
|
.. |thumbnail_url_mandatory| replace:: Removal of the deprecated argument ``thumb_url`` made ``thumbnail_url`` mandatory.
|
||||||
|
|
||||||
.. |async_context_manager| replace:: Asynchronous context manager which
|
.. |async_context_manager| replace:: Asynchronous context manager which
|
||||||
|
|
||||||
.. |reply_parameters| replace:: Description of the message to reply to.
|
.. |reply_parameters| replace:: Description of the message to reply to.
|
||||||
|
|
|
@ -67,7 +67,7 @@ all = [
|
||||||
]
|
]
|
||||||
callback-data = [
|
callback-data = [
|
||||||
# Cachetools doesn't have a strict stability policy. Let's be cautious for now.
|
# Cachetools doesn't have a strict stability policy. Let's be cautious for now.
|
||||||
"cachetools>=5.3.3,<5.5.0",
|
"cachetools>=5.3.3,<5.6.0",
|
||||||
]
|
]
|
||||||
ext = [
|
ext = [
|
||||||
"python-telegram-bot[callback-data,job-queue,rate-limiter,webhooks]",
|
"python-telegram-bot[callback-data,job-queue,rate-limiter,webhooks]",
|
||||||
|
|
|
@ -204,6 +204,7 @@ __all__ = (
|
||||||
"ReactionType",
|
"ReactionType",
|
||||||
"ReactionTypeCustomEmoji",
|
"ReactionTypeCustomEmoji",
|
||||||
"ReactionTypeEmoji",
|
"ReactionTypeEmoji",
|
||||||
|
"ReactionTypePaid",
|
||||||
"RefundedPayment",
|
"RefundedPayment",
|
||||||
"ReplyKeyboardMarkup",
|
"ReplyKeyboardMarkup",
|
||||||
"ReplyKeyboardRemove",
|
"ReplyKeyboardRemove",
|
||||||
|
@ -467,7 +468,13 @@ from ._payment.stars import (
|
||||||
from ._payment.successfulpayment import SuccessfulPayment
|
from ._payment.successfulpayment import SuccessfulPayment
|
||||||
from ._poll import InputPollOption, Poll, PollAnswer, PollOption
|
from ._poll import InputPollOption, Poll, PollAnswer, PollOption
|
||||||
from ._proximityalerttriggered import ProximityAlertTriggered
|
from ._proximityalerttriggered import ProximityAlertTriggered
|
||||||
from ._reaction import ReactionCount, ReactionType, ReactionTypeCustomEmoji, ReactionTypeEmoji
|
from ._reaction import (
|
||||||
|
ReactionCount,
|
||||||
|
ReactionType,
|
||||||
|
ReactionTypeCustomEmoji,
|
||||||
|
ReactionTypeEmoji,
|
||||||
|
ReactionTypePaid,
|
||||||
|
)
|
||||||
from ._reply import ExternalReplyInfo, ReplyParameters, TextQuote
|
from ._reply import ExternalReplyInfo, ReplyParameters, TextQuote
|
||||||
from ._replykeyboardmarkup import ReplyKeyboardMarkup
|
from ._replykeyboardmarkup import ReplyKeyboardMarkup
|
||||||
from ._replykeyboardremove import ReplyKeyboardRemove
|
from ._replykeyboardremove import ReplyKeyboardRemove
|
||||||
|
|
175
telegram/_bot.py
175
telegram/_bot.py
|
@ -18,6 +18,7 @@
|
||||||
# You should have received a copy of the GNU Lesser Public License
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains an object that represents a Telegram Bot."""
|
"""This module contains an object that represents a Telegram Bot."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import contextlib
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
|
@ -4427,18 +4428,6 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
||||||
If you're having any trouble setting up webhooks, please check out this `guide to
|
If you're having any trouble setting up webhooks, please check out this `guide to
|
||||||
Webhooks`_.
|
Webhooks`_.
|
||||||
|
|
||||||
Note:
|
|
||||||
1. You will not be able to receive updates using :meth:`get_updates` for long as an
|
|
||||||
outgoing webhook is set up.
|
|
||||||
2. To use a self-signed certificate, you need to upload your public key certificate
|
|
||||||
using certificate parameter. Please upload as InputFile, sending a String will not
|
|
||||||
work.
|
|
||||||
3. Ports currently supported for Webhooks:
|
|
||||||
:attr:`telegram.constants.SUPPORTED_WEBHOOK_PORTS`.
|
|
||||||
|
|
||||||
If you're having any trouble setting up webhooks, please check out this `guide to
|
|
||||||
Webhooks`_.
|
|
||||||
|
|
||||||
.. seealso:: :meth:`telegram.ext.Application.run_webhook`,
|
.. seealso:: :meth:`telegram.ext.Application.run_webhook`,
|
||||||
:meth:`telegram.ext.Updater.start_webhook`
|
:meth:`telegram.ext.Updater.start_webhook`
|
||||||
|
|
||||||
|
@ -5019,7 +5008,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
||||||
payload (:obj:`str`): Bot-defined invoice payload.
|
payload (:obj:`str`): Bot-defined invoice payload.
|
||||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||||
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
|
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
|
||||||
displayed to the user, use for your internal processes.
|
displayed to the user, use it for your internal processes.
|
||||||
provider_token (:obj:`str`): Payments provider token, obtained via
|
provider_token (:obj:`str`): Payments provider token, obtained via
|
||||||
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|
||||||
|tg_stars|.
|
|tg_stars|.
|
||||||
|
@ -5785,10 +5774,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
||||||
invite_link (:obj:`str` | :obj:`telegram.ChatInviteLink`): The invite link to edit.
|
invite_link (:obj:`str` | :class:`telegram.ChatInviteLink`): The invite link to edit.
|
||||||
|
|
||||||
.. versionchanged:: 20.0
|
.. versionchanged:: 20.0
|
||||||
Now also accepts :obj:`telegram.ChatInviteLink` instances.
|
Now also accepts :class:`telegram.ChatInviteLink` instances.
|
||||||
expire_date (:obj:`int` | :obj:`datetime.datetime`, optional): Date when the link will
|
expire_date (:obj:`int` | :obj:`datetime.datetime`, optional): Date when the link will
|
||||||
expire.
|
expire.
|
||||||
For timezone naive :obj:`datetime.datetime` objects, the default timezone of the
|
For timezone naive :obj:`datetime.datetime` objects, the default timezone of the
|
||||||
|
@ -5857,10 +5846,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
||||||
invite_link (:obj:`str` | :obj:`telegram.ChatInviteLink`): The invite link to revoke.
|
invite_link (:obj:`str` | :class:`telegram.ChatInviteLink`): The invite link to revoke.
|
||||||
|
|
||||||
.. versionchanged:: 20.0
|
.. versionchanged:: 20.0
|
||||||
Now also accepts :obj:`telegram.ChatInviteLink` instances.
|
Now also accepts :class:`telegram.ChatInviteLink` instances.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:class:`telegram.ChatInviteLink`
|
:class:`telegram.ChatInviteLink`
|
||||||
|
@ -6156,7 +6145,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
||||||
business_connection_id (:obj:`str`, optional): Unique identifier of the business
|
business_connection_id (:obj:`str`, optional): Unique identifier of the business
|
||||||
connection on behalf of which the message will be pinned.
|
connection on behalf of which the message will be pinned.
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`bool`: On success, :obj:`True` is returned.
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
@ -6209,7 +6198,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
||||||
business_connection_id (:obj:`str`, optional): Unique identifier of the business
|
business_connection_id (:obj:`str`, optional): Unique identifier of the business
|
||||||
connection on behalf of which the message will be unpinned.
|
connection on behalf of which the message will be unpinned.
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`bool`: On success, :obj:`True` is returned.
|
:obj:`bool`: On success, :obj:`True` is returned.
|
||||||
|
@ -7402,8 +7391,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
.. versionadded:: 20.0
|
.. versionadded:: 20.0
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
rights (:obj:`telegram.ChatAdministratorRights`, optional): A
|
rights (:class:`telegram.ChatAdministratorRights`, optional): A
|
||||||
:obj:`telegram.ChatAdministratorRights` object describing new default administrator
|
:class:`telegram.ChatAdministratorRights` object describing new default
|
||||||
|
administrator
|
||||||
rights. If not specified, the default administrator rights will be cleared.
|
rights. If not specified, the default administrator rights will be cleared.
|
||||||
for_channels (:obj:`bool`, optional): Pass :obj:`True` to change the default
|
for_channels (:obj:`bool`, optional): Pass :obj:`True` to change the default
|
||||||
administrator rights of the bot in channels. Otherwise, the default administrator
|
administrator rights of the bot in channels. Otherwise, the default administrator
|
||||||
|
@ -7413,7 +7403,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
:obj:`bool`: Returns :obj:`True` on success.
|
:obj:`bool`: Returns :obj:`True` on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:obj:`telegram.error.TelegramError`
|
:exc:`telegram.error.TelegramError`
|
||||||
"""
|
"""
|
||||||
data: JSONDict = {"rights": rights, "for_channels": for_channels}
|
data: JSONDict = {"rights": rights, "for_channels": for_channels}
|
||||||
|
|
||||||
|
@ -7979,7 +7969,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
payload (:obj:`str`): Bot-defined invoice payload.
|
payload (:obj:`str`): Bot-defined invoice payload.
|
||||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||||
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
|
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
|
||||||
displayed to the user, use for your internal processes.
|
displayed to the user, use it for your internal processes.
|
||||||
provider_token (:obj:`str`): Payments provider token, obtained via
|
provider_token (:obj:`str`): Payments provider token, obtained via
|
||||||
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|
||||||
|tg_stars|.
|
|tg_stars|.
|
||||||
|
@ -8179,7 +8169,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must
|
Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must
|
||||||
be an administrator in the chat for this to work and must have
|
be an administrator in the chat for this to work and must have the
|
||||||
:paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
|
:paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
|
||||||
unless it is the creator of the topic.
|
unless it is the creator of the topic.
|
||||||
|
|
||||||
|
@ -8447,7 +8437,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot
|
Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot
|
||||||
must be an administrator in the chat for this to work and must have
|
must be an administrator in the chat for this to work and must have the
|
||||||
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
||||||
|
|
||||||
.. versionadded:: 20.0
|
.. versionadded:: 20.0
|
||||||
|
@ -8946,7 +8936,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
"""
|
"""
|
||||||
Use this method to change the chosen reactions on a message. Service messages can't be
|
Use this method to change the chosen reactions on a message. Service messages can't be
|
||||||
reacted to. Automatically forwarded messages from a channel to its discussion group have
|
reacted to. Automatically forwarded messages from a channel to its discussion group have
|
||||||
the same available reactions as messages in the channel.
|
the same available reactions as messages in the channel. Bots can't use paid reactions.
|
||||||
|
|
||||||
.. versionadded:: 20.8
|
.. versionadded:: 20.8
|
||||||
|
|
||||||
|
@ -8959,7 +8949,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
:class:`telegram.ReactionType` | :obj:`str`, optional): A list of reaction
|
:class:`telegram.ReactionType` | :obj:`str`, optional): A list of reaction
|
||||||
types to set on the message. Currently, as non-premium users, bots can set up to
|
types to set on the message. Currently, as non-premium users, bots can set up to
|
||||||
one reaction per message. A custom emoji reaction can be used if it is either
|
one reaction per message. A custom emoji reaction can be used if it is either
|
||||||
already present on the message or explicitly allowed by chat administrators.
|
already present on the message or explicitly allowed by chat administrators. Paid
|
||||||
|
reactions can't be used by bots.
|
||||||
|
|
||||||
Tip:
|
Tip:
|
||||||
Passed :obj:`str` values will be converted to either
|
Passed :obj:`str` values will be converted to either
|
||||||
|
@ -9076,7 +9067,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
user_id (:obj:`int`): User identifier of the sticker set owner.
|
user_id (:obj:`int`): User identifier of the sticker set owner.
|
||||||
name (:obj:`str`): Sticker set name.
|
name (:obj:`str`): Sticker set name.
|
||||||
old_sticker (:obj:`str`): File identifier of the replaced sticker.
|
old_sticker (:obj:`str`): File identifier of the replaced sticker.
|
||||||
sticker (:obj:`telegram.InputSticker`): An object with information about the added
|
sticker (:class:`telegram.InputSticker`): An object with information about the added
|
||||||
sticker. If exactly the same sticker had already been added to the set, then the
|
sticker. If exactly the same sticker had already been added to the set, then the
|
||||||
set remains unchanged.
|
set remains unchanged.
|
||||||
|
|
||||||
|
@ -9201,6 +9192,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||||
reply_parameters: Optional["ReplyParameters"] = None,
|
reply_parameters: Optional["ReplyParameters"] = None,
|
||||||
reply_markup: Optional[ReplyMarkup] = None,
|
reply_markup: Optional[ReplyMarkup] = None,
|
||||||
|
business_connection_id: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||||
reply_to_message_id: Optional[int] = None,
|
reply_to_message_id: Optional[int] = None,
|
||||||
|
@ -9210,12 +9202,14 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
api_kwargs: Optional[JSONDict] = None,
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
) -> Message:
|
) -> Message:
|
||||||
"""Use this method to send paid media to channel chats.
|
"""Use this method to send paid media.
|
||||||
|
|
||||||
.. versionadded:: 21.4
|
.. versionadded:: 21.4
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel| If the chat is a channel, all
|
||||||
|
Telegram Star proceeds from this media will be credited to the chat's balance.
|
||||||
|
Otherwise, they will be credited to the bot's balance.
|
||||||
star_count (:obj:`int`): The number of Telegram Stars that must be paid to buy access
|
star_count (:obj:`int`): The number of Telegram Stars that must be paid to buy access
|
||||||
to the media.
|
to the media.
|
||||||
media (Sequence[:class:`telegram.InputPaidMedia`]): A list describing the media to be
|
media (Sequence[:class:`telegram.InputPaidMedia`]): A list describing the media to be
|
||||||
|
@ -9233,6 +9227,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
:class:`ReplyKeyboardRemove` | :class:`ForceReply`, optional):
|
:class:`ReplyKeyboardRemove` | :class:`ForceReply`, optional):
|
||||||
Additional interface options. An object for an inline keyboard, custom reply
|
Additional interface options. An object for an inline keyboard, custom reply
|
||||||
keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
||||||
|
business_connection_id (:obj:`str`, optional): |business_id_str|
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Keyword Args:
|
Keyword Args:
|
||||||
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
|
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
|
||||||
|
@ -9274,8 +9271,122 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
connect_timeout=connect_timeout,
|
connect_timeout=connect_timeout,
|
||||||
pool_timeout=pool_timeout,
|
pool_timeout=pool_timeout,
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
|
business_connection_id=business_connection_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def create_chat_subscription_invite_link(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
subscription_period: int,
|
||||||
|
subscription_price: int,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
) -> ChatInviteLink:
|
||||||
|
"""
|
||||||
|
Use this method to create a `subscription invite link <https://telegram.org/blog/\
|
||||||
|
superchannels-star-reactions-subscriptions#star-subscriptions>`_ for a channel chat.
|
||||||
|
The bot must have the :attr:`~telegram.ChatPermissions.can_invite_users` administrator
|
||||||
|
right. The link can be edited using the :meth:`edit_chat_subscription_invite_link` or
|
||||||
|
revoked using the :meth:`revoke_chat_invite_link`.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
||||||
|
subscription_period (:obj:`int`): The number of seconds the subscription will be
|
||||||
|
active for before the next payment. Currently, it must always be
|
||||||
|
:tg-const:`telegram.constants.ChatSubscriptionLimit.SUBSCRIPTION_PERIOD` (30 days).
|
||||||
|
subscription_price (:obj:`int`): The number of Telegram Stars a user must pay initially
|
||||||
|
and after each subsequent subscription period to be a member of the chat;
|
||||||
|
:tg-const:`telegram.constants.ChatSubscriptionLimit.MIN_PRICE`-
|
||||||
|
:tg-const:`telegram.constants.ChatSubscriptionLimit.MAX_PRICE`.
|
||||||
|
name (:obj:`str`, optional): Invite link name;
|
||||||
|
0-:tg-const:`telegram.constants.ChatInviteLinkLimit.NAME_LENGTH` characters.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:class:`telegram.ChatInviteLink`
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.error.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
data: JSONDict = {
|
||||||
|
"chat_id": chat_id,
|
||||||
|
"subscription_period": subscription_period,
|
||||||
|
"subscription_price": subscription_price,
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await self._post(
|
||||||
|
"createChatSubscriptionInviteLink",
|
||||||
|
data,
|
||||||
|
read_timeout=read_timeout,
|
||||||
|
write_timeout=write_timeout,
|
||||||
|
connect_timeout=connect_timeout,
|
||||||
|
pool_timeout=pool_timeout,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
return ChatInviteLink.de_json(result, self) # type: ignore[return-value]
|
||||||
|
|
||||||
|
async def edit_chat_subscription_invite_link(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
invite_link: Union[str, "ChatInviteLink"],
|
||||||
|
name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
) -> ChatInviteLink:
|
||||||
|
"""
|
||||||
|
Use this method to edit a subscription invite link created by the bot. The bot must have
|
||||||
|
:attr:`telegram.ChatPermissions.can_invite_users` administrator right.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
|
||||||
|
invite_link (:obj:`str` | :obj:`telegram.ChatInviteLink`): The invite link to edit.
|
||||||
|
name (:obj:`str`, optional): Invite link name;
|
||||||
|
0-:tg-const:`telegram.constants.ChatInviteLinkLimit.NAME_LENGTH` characters.
|
||||||
|
|
||||||
|
Tip:
|
||||||
|
Omitting this argument removes the name of the invite link.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:class:`telegram.ChatInviteLink`
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`telegram.error.TelegramError`
|
||||||
|
|
||||||
|
"""
|
||||||
|
link = invite_link.invite_link if isinstance(invite_link, ChatInviteLink) else invite_link
|
||||||
|
data: JSONDict = {
|
||||||
|
"chat_id": chat_id,
|
||||||
|
"invite_link": link,
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await self._post(
|
||||||
|
"editChatSubscriptionInviteLink",
|
||||||
|
data,
|
||||||
|
read_timeout=read_timeout,
|
||||||
|
write_timeout=write_timeout,
|
||||||
|
connect_timeout=connect_timeout,
|
||||||
|
pool_timeout=pool_timeout,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
return ChatInviteLink.de_json(result, self) # type: ignore[return-value]
|
||||||
|
|
||||||
def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
|
def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
|
||||||
"""See :meth:`telegram.TelegramObject.to_dict`."""
|
"""See :meth:`telegram.TelegramObject.to_dict`."""
|
||||||
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
|
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
|
||||||
|
@ -9532,3 +9643,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||||
"""Alias for :meth:`get_star_transactions`"""
|
"""Alias for :meth:`get_star_transactions`"""
|
||||||
sendPaidMedia = send_paid_media
|
sendPaidMedia = send_paid_media
|
||||||
"""Alias for :meth:`send_paid_media`"""
|
"""Alias for :meth:`send_paid_media`"""
|
||||||
|
createChatSubscriptionInviteLink = create_chat_subscription_invite_link
|
||||||
|
"""Alias for :meth:`create_chat_subscription_invite_link`"""
|
||||||
|
editChatSubscriptionInviteLink = edit_chat_subscription_invite_link
|
||||||
|
"""Alias for :meth:`edit_chat_subscription_invite_link`"""
|
||||||
|
|
|
@ -2666,6 +2666,81 @@ class _ChatBase(TelegramObject):
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def create_subscription_invite_link(
|
||||||
|
self,
|
||||||
|
subscription_period: int,
|
||||||
|
subscription_price: int,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
) -> "ChatInviteLink":
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
await bot.create_chat_subscription_invite_link(
|
||||||
|
chat_id=update.effective_chat.id, *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.create_chat_subscription_invite_link`.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:class:`telegram.ChatInviteLink`
|
||||||
|
"""
|
||||||
|
return await self.get_bot().create_chat_subscription_invite_link(
|
||||||
|
chat_id=self.id,
|
||||||
|
subscription_period=subscription_period,
|
||||||
|
subscription_price=subscription_price,
|
||||||
|
name=name,
|
||||||
|
read_timeout=read_timeout,
|
||||||
|
write_timeout=write_timeout,
|
||||||
|
connect_timeout=connect_timeout,
|
||||||
|
pool_timeout=pool_timeout,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def edit_subscription_invite_link(
|
||||||
|
self,
|
||||||
|
invite_link: Union[str, "ChatInviteLink"],
|
||||||
|
name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
) -> "ChatInviteLink":
|
||||||
|
"""Shortcut for::
|
||||||
|
|
||||||
|
await bot.edit_chat_subscription_invite_link(
|
||||||
|
chat_id=update.effective_chat.id, *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
For the documentation of the arguments, please see
|
||||||
|
:meth:`telegram.Bot.edit_chat_subscription_invite_link`.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
:class:`telegram.ChatInviteLink`
|
||||||
|
|
||||||
|
"""
|
||||||
|
return await self.get_bot().edit_chat_subscription_invite_link(
|
||||||
|
chat_id=self.id,
|
||||||
|
invite_link=invite_link,
|
||||||
|
read_timeout=read_timeout,
|
||||||
|
write_timeout=write_timeout,
|
||||||
|
connect_timeout=connect_timeout,
|
||||||
|
pool_timeout=pool_timeout,
|
||||||
|
api_kwargs=api_kwargs,
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
|
||||||
async def approve_join_request(
|
async def approve_join_request(
|
||||||
self,
|
self,
|
||||||
user_id: int,
|
user_id: int,
|
||||||
|
@ -3274,6 +3349,7 @@ class _ChatBase(TelegramObject):
|
||||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||||
reply_parameters: Optional["ReplyParameters"] = None,
|
reply_parameters: Optional["ReplyParameters"] = None,
|
||||||
reply_markup: Optional[ReplyMarkup] = None,
|
reply_markup: Optional[ReplyMarkup] = None,
|
||||||
|
business_connection_id: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||||
reply_to_message_id: Optional[int] = None,
|
reply_to_message_id: Optional[int] = None,
|
||||||
|
@ -3314,6 +3390,7 @@ class _ChatBase(TelegramObject):
|
||||||
connect_timeout=connect_timeout,
|
connect_timeout=connect_timeout,
|
||||||
pool_timeout=pool_timeout,
|
pool_timeout=pool_timeout,
|
||||||
api_kwargs=api_kwargs,
|
api_kwargs=api_kwargs,
|
||||||
|
business_connection_id=business_connection_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,7 @@ class BackgroundTypeFill(BackgroundType):
|
||||||
.. versionadded:: 21.2
|
.. versionadded:: 21.2
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fill (:obj:`telegram.BackgroundFill`): The background fill.
|
fill (:class:`telegram.BackgroundFill`): The background fill.
|
||||||
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
||||||
percentage;
|
percentage;
|
||||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||||
|
@ -315,7 +315,7 @@ class BackgroundTypeFill(BackgroundType):
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): Type of the background. Always
|
type (:obj:`str`): Type of the background. Always
|
||||||
:attr:`~telegram.BackgroundType.FILL`.
|
:attr:`~telegram.BackgroundType.FILL`.
|
||||||
fill (:obj:`telegram.BackgroundFill`): The background fill.
|
fill (:class:`telegram.BackgroundFill`): The background fill.
|
||||||
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
||||||
percentage;
|
percentage;
|
||||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||||
|
@ -349,7 +349,7 @@ class BackgroundTypeWallpaper(BackgroundType):
|
||||||
.. versionadded:: 21.2
|
.. versionadded:: 21.2
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
document (:obj:`telegram.Document`): Document with the wallpaper
|
document (:class:`telegram.Document`): Document with the wallpaper
|
||||||
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
||||||
percentage;
|
percentage;
|
||||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||||
|
@ -361,7 +361,7 @@ class BackgroundTypeWallpaper(BackgroundType):
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): Type of the background. Always
|
type (:obj:`str`): Type of the background. Always
|
||||||
:attr:`~telegram.BackgroundType.WALLPAPER`.
|
:attr:`~telegram.BackgroundType.WALLPAPER`.
|
||||||
document (:obj:`telegram.Document`): Document with the wallpaper
|
document (:class:`telegram.Document`): Document with the wallpaper
|
||||||
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
|
||||||
percentage;
|
percentage;
|
||||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||||
|
@ -407,8 +407,8 @@ class BackgroundTypePattern(BackgroundType):
|
||||||
.. versionadded:: 21.2
|
.. versionadded:: 21.2
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
document (:obj:`telegram.Document`): Document with the pattern.
|
document (:class:`telegram.Document`): Document with the pattern.
|
||||||
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
|
fill (:class:`telegram.BackgroundFill`): The background fill that is combined with
|
||||||
the pattern.
|
the pattern.
|
||||||
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
|
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
|
||||||
background;
|
background;
|
||||||
|
@ -422,8 +422,8 @@ class BackgroundTypePattern(BackgroundType):
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): Type of the background. Always
|
type (:obj:`str`): Type of the background. Always
|
||||||
:attr:`~telegram.BackgroundType.PATTERN`.
|
:attr:`~telegram.BackgroundType.PATTERN`.
|
||||||
document (:obj:`telegram.Document`): Document with the pattern.
|
document (:class:`telegram.Document`): Document with the pattern.
|
||||||
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
|
fill (:class:`telegram.BackgroundFill`): The background fill that is combined with
|
||||||
the pattern.
|
the pattern.
|
||||||
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
|
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
|
||||||
background;
|
background;
|
||||||
|
@ -511,10 +511,10 @@ class ChatBackground(TelegramObject):
|
||||||
.. versionadded:: 21.2
|
.. versionadded:: 21.2
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
type (:obj:`telegram.BackgroundType`): Type of the background.
|
type (:class:`telegram.BackgroundType`): Type of the background.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`telegram.BackgroundType`): Type of the background.
|
type (:class:`telegram.BackgroundType`): Type of the background.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("type",)
|
__slots__ = ("type",)
|
||||||
|
|
|
@ -78,7 +78,7 @@ class ChatFullInfo(_ChatBase):
|
||||||
#collectible-usernames>`_; for private chats, supergroups and channels.
|
#collectible-usernames>`_; for private chats, supergroups and channels.
|
||||||
|
|
||||||
.. versionadded:: 20.0
|
.. versionadded:: 20.0
|
||||||
birthdate (:obj:`telegram.Birthdate`, optional): For private chats,
|
birthdate (:class:`telegram.Birthdate`, optional): For private chats,
|
||||||
the date of birth of the user.
|
the date of birth of the user.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
|
@ -94,8 +94,8 @@ class ChatFullInfo(_ChatBase):
|
||||||
chats with business accounts, the opening hours of the business.
|
chats with business accounts, the opening hours of the business.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of
|
personal_chat (:class:`telegram.Chat`, optional): For private chats, the personal channel
|
||||||
the user.
|
of the user.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available
|
available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available
|
||||||
|
@ -232,7 +232,7 @@ class ChatFullInfo(_ChatBase):
|
||||||
obtained via :meth:`~telegram.Bot.get_chat`.
|
obtained via :meth:`~telegram.Bot.get_chat`.
|
||||||
|
|
||||||
.. versionadded:: 20.0
|
.. versionadded:: 20.0
|
||||||
birthdate (:obj:`telegram.Birthdate`): Optional. For private chats,
|
birthdate (:class:`telegram.Birthdate`): Optional. For private chats,
|
||||||
the date of birth of the user.
|
the date of birth of the user.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
|
@ -248,8 +248,8 @@ class ChatFullInfo(_ChatBase):
|
||||||
chats with business accounts, the opening hours of the business.
|
chats with business accounts, the opening hours of the business.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of
|
personal_chat (:class:`telegram.Chat`): Optional. For private chats, the personal channel
|
||||||
the user.
|
of the user.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
|
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
|
||||||
|
|
|
@ -69,6 +69,16 @@ class ChatInviteLink(TelegramObject):
|
||||||
created using this link.
|
created using this link.
|
||||||
|
|
||||||
.. versionadded:: 13.8
|
.. versionadded:: 13.8
|
||||||
|
subscription_period (:obj:`int`, optional): The number of seconds the subscription will be
|
||||||
|
active for before the next payment.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
subscription_price (:obj:`int`, optional): The amount of Telegram Stars a user must pay
|
||||||
|
initially and after each subsequent subscription period to be a member of the chat
|
||||||
|
using the link.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
invite_link (:obj:`str`): The invite link. If the link was created by another chat
|
invite_link (:obj:`str`): The invite link. If the link was created by another chat
|
||||||
administrator, then the second part of the link will be replaced with ``'…'``.
|
administrator, then the second part of the link will be replaced with ``'…'``.
|
||||||
|
@ -96,6 +106,15 @@ class ChatInviteLink(TelegramObject):
|
||||||
created using this link.
|
created using this link.
|
||||||
|
|
||||||
.. versionadded:: 13.8
|
.. versionadded:: 13.8
|
||||||
|
subscription_period (:obj:`int`): Optional. The number of seconds the subscription will be
|
||||||
|
active for before the next payment.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
subscription_price (:obj:`int`): Optional. The amount of Telegram Stars a user must pay
|
||||||
|
initially and after each subsequent subscription period to be a member of the chat
|
||||||
|
using the link.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -109,6 +128,8 @@ class ChatInviteLink(TelegramObject):
|
||||||
"member_limit",
|
"member_limit",
|
||||||
"name",
|
"name",
|
||||||
"pending_join_request_count",
|
"pending_join_request_count",
|
||||||
|
"subscription_period",
|
||||||
|
"subscription_price",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -122,6 +143,8 @@ class ChatInviteLink(TelegramObject):
|
||||||
member_limit: Optional[int] = None,
|
member_limit: Optional[int] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
pending_join_request_count: Optional[int] = None,
|
pending_join_request_count: Optional[int] = None,
|
||||||
|
subscription_period: Optional[int] = None,
|
||||||
|
subscription_price: Optional[int] = None,
|
||||||
*,
|
*,
|
||||||
api_kwargs: Optional[JSONDict] = None,
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
):
|
):
|
||||||
|
@ -140,6 +163,9 @@ class ChatInviteLink(TelegramObject):
|
||||||
self.pending_join_request_count: Optional[int] = (
|
self.pending_join_request_count: Optional[int] = (
|
||||||
int(pending_join_request_count) if pending_join_request_count is not None else None
|
int(pending_join_request_count) if pending_join_request_count is not None else None
|
||||||
)
|
)
|
||||||
|
self.subscription_period: Optional[int] = subscription_period
|
||||||
|
self.subscription_price: Optional[int] = subscription_price
|
||||||
|
|
||||||
self._id_attrs = (
|
self._id_attrs = (
|
||||||
self.invite_link,
|
self.invite_link,
|
||||||
self.creates_join_request,
|
self.creates_join_request,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
# You should have received a copy of the GNU Lesser Public License
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains an object that represents a Telegram ChatMember."""
|
"""This module contains an object that represents a Telegram ChatMember."""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
|
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
|
||||||
|
|
||||||
|
@ -391,24 +392,34 @@ class ChatMemberMember(ChatMember):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user (:class:`telegram.User`): Information about the user.
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
until_date (:class:`datetime.datetime`, optional): Date when the user's subscription will
|
||||||
|
expire.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
status (:obj:`str`): The member's status in the chat,
|
status (:obj:`str`): The member's status in the chat,
|
||||||
always :tg-const:`telegram.ChatMember.MEMBER`.
|
always :tg-const:`telegram.ChatMember.MEMBER`.
|
||||||
user (:class:`telegram.User`): Information about the user.
|
user (:class:`telegram.User`): Information about the user.
|
||||||
|
until_date (:class:`datetime.datetime`): Optional. Date when the user's subscription will
|
||||||
|
expire.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ("until_date",)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
user: User,
|
user: User,
|
||||||
|
until_date: Optional[datetime.datetime] = None,
|
||||||
*,
|
*,
|
||||||
api_kwargs: Optional[JSONDict] = None,
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
):
|
):
|
||||||
super().__init__(status=ChatMember.MEMBER, user=user, api_kwargs=api_kwargs)
|
super().__init__(status=ChatMember.MEMBER, user=user, api_kwargs=api_kwargs)
|
||||||
self._freeze()
|
with self._unfrozen():
|
||||||
|
self.until_date: Optional[datetime.datetime] = until_date
|
||||||
|
|
||||||
|
|
||||||
class ChatMemberRestricted(ChatMember):
|
class ChatMemberRestricted(ChatMember):
|
||||||
|
|
|
@ -78,7 +78,7 @@ class InputFile:
|
||||||
# here the file handle is already closed and the upload will fail
|
# here the file handle is already closed and the upload will fail
|
||||||
await bot.send_document(chat_id, input_file)
|
await bot.send_document(chat_id, input_file)
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -126,7 +126,7 @@ class InputFile:
|
||||||
def field_tuple(self) -> FieldTuple:
|
def field_tuple(self) -> FieldTuple:
|
||||||
"""Field tuple representing the contents of the file for upload to the Telegram servers.
|
"""Field tuple representing the contents of the file for upload to the Telegram servers.
|
||||||
|
|
||||||
.. versionchanged:: NEXT.VERSION
|
.. versionchanged:: 21.5
|
||||||
Content may now be a file handle.
|
Content may now be a file handle.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
|
@ -49,7 +49,7 @@ class InputSticker(TelegramObject):
|
||||||
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
|
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
|
||||||
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
|
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
|
||||||
sticker.
|
sticker.
|
||||||
mask_position (:obj:`telegram.MaskPosition`, optional): Position where the mask should be
|
mask_position (:class:`telegram.MaskPosition`, optional): Position where the mask should be
|
||||||
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
|
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
|
||||||
keywords (Sequence[:obj:`str`], optional): Sequence of
|
keywords (Sequence[:obj:`str`], optional): Sequence of
|
||||||
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
|
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
|
||||||
|
@ -71,7 +71,7 @@ class InputSticker(TelegramObject):
|
||||||
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
|
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
|
||||||
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
|
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
|
||||||
sticker.
|
sticker.
|
||||||
mask_position (:obj:`telegram.MaskPosition`): Optional. Position where the mask should be
|
mask_position (:class:`telegram.MaskPosition`): Optional. Position where the mask should be
|
||||||
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
|
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
|
||||||
keywords (Tuple[:obj:`str`]): Optional. Tuple of
|
keywords (Tuple[:obj:`str`]): Optional. Tuple of
|
||||||
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
|
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
|
||||||
|
|
|
@ -126,7 +126,7 @@ class Giveaway(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["Giveaway"]:
|
) -> Optional["Giveaway"]:
|
||||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -262,7 +262,7 @@ class GiveawayWinners(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["GiveawayWinners"]:
|
) -> Optional["GiveawayWinners"]:
|
||||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -330,7 +330,7 @@ class GiveawayCompleted(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["GiveawayCompleted"]:
|
) -> Optional["GiveawayCompleted"]:
|
||||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
|
|
@ -99,7 +99,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||||
|
|
||||||
.. seealso:: :wiki:`Arbitrary callback_data <Arbitrary-callback_data>`
|
.. seealso:: :wiki:`Arbitrary callback_data <Arbitrary-callback_data>`
|
||||||
|
|
||||||
web_app (:obj:`telegram.WebAppInfo`, optional): Description of the `Web App
|
web_app (:class:`telegram.WebAppInfo`, optional): Description of the `Web App
|
||||||
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
|
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
|
||||||
the button. The Web App will be able to send an arbitrary message on behalf of the user
|
the button. The Web App will be able to send an arbitrary message on behalf of the user
|
||||||
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
|
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
|
||||||
|
@ -107,16 +107,14 @@ class InlineKeyboardButton(TelegramObject):
|
||||||
a Telegram Business account.
|
a Telegram Business account.
|
||||||
|
|
||||||
.. versionadded:: 20.0
|
.. versionadded:: 20.0
|
||||||
switch_inline_query (:obj:`str`, optional): If set, pressing the button will insert the
|
switch_inline_query (:obj:`str`, optional): If set, pressing the button will prompt the
|
||||||
bot's username and the specified inline query in the current chat's input field. May be
|
user to select one of their chats, open that chat and insert the bot's username and the
|
||||||
empty, in which case only the bot's username will be inserted.
|
specified inline query in the input field. May be empty, in which case just the bot's
|
||||||
|
username will be inserted. Not supported for messages sent on behalf of a Telegram
|
||||||
This offers a quick way for the user to open your bot in inline mode in the same chat -
|
Business account.
|
||||||
good for selecting something from multiple options. Not supported in channels and for
|
|
||||||
messages sent on behalf of a Telegram Business account.
|
|
||||||
|
|
||||||
Tip:
|
Tip:
|
||||||
This is similar to the new parameter :paramref:`switch_inline_query_chosen_chat`,
|
This is similar to the parameter :paramref:`switch_inline_query_chosen_chat`,
|
||||||
but gives no control over which chats can be selected.
|
but gives no control over which chats can be selected.
|
||||||
switch_inline_query_current_chat (:obj:`str`, optional): If set, pressing the button will
|
switch_inline_query_current_chat (:obj:`str`, optional): If set, pressing the button will
|
||||||
insert the bot's username and the specified inline query in the current chat's input
|
insert the bot's username and the specified inline query in the current chat's input
|
||||||
|
@ -137,7 +135,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||||
Note:
|
Note:
|
||||||
This type of button **must** always be the first button in the first row and can
|
This type of button **must** always be the first button in the first row and can
|
||||||
only be used in invoice messages.
|
only be used in invoice messages.
|
||||||
switch_inline_query_chosen_chat (:obj:`telegram.SwitchInlineQueryChosenChat`, optional):
|
switch_inline_query_chosen_chat (:class:`telegram.SwitchInlineQueryChosenChat`, optional):
|
||||||
If set, pressing the button will prompt the user to select one of their chats of the
|
If set, pressing the button will prompt the user to select one of their chats of the
|
||||||
specified type, open that chat and insert the bot's username and the specified inline
|
specified type, open that chat and insert the bot's username and the specified inline
|
||||||
query in the input field. Not supported for messages sent on behalf of a Telegram
|
query in the input field. Not supported for messages sent on behalf of a Telegram
|
||||||
|
@ -170,7 +168,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||||
to the bot when the button is pressed, UTF-8
|
to the bot when the button is pressed, UTF-8
|
||||||
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
|
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
|
||||||
:tg-const:`telegram.InlineKeyboardButton.MAX_CALLBACK_DATA` bytes.
|
:tg-const:`telegram.InlineKeyboardButton.MAX_CALLBACK_DATA` bytes.
|
||||||
web_app (:obj:`telegram.WebAppInfo`): Optional. Description of the `Web App
|
web_app (:class:`telegram.WebAppInfo`): Optional. Description of the `Web App
|
||||||
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
|
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
|
||||||
the button. The Web App will be able to send an arbitrary message on behalf of the user
|
the button. The Web App will be able to send an arbitrary message on behalf of the user
|
||||||
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
|
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
|
||||||
|
@ -178,16 +176,14 @@ class InlineKeyboardButton(TelegramObject):
|
||||||
a Telegram Business account.
|
a Telegram Business account.
|
||||||
|
|
||||||
.. versionadded:: 20.0
|
.. versionadded:: 20.0
|
||||||
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will insert the
|
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will prompt the
|
||||||
bot's username and the specified inline query in the current chat's input field. May be
|
user to select one of their chats, open that chat and insert the bot's username and the
|
||||||
empty, in which case only the bot's username will be inserted.
|
specified inline query in the input field. May be empty, in which case just the bot's
|
||||||
|
username will be inserted. Not supported for messages sent on behalf of a Telegram
|
||||||
This offers a quick way for the user to open your bot in inline mode in the same chat -
|
Business account.
|
||||||
good for selecting something from multiple options. Not supported in channels and for
|
|
||||||
messages sent on behalf of a Telegram Business account.
|
|
||||||
|
|
||||||
Tip:
|
Tip:
|
||||||
This is similar to the new parameter :paramref:`switch_inline_query_chosen_chat`,
|
This is similar to the parameter :paramref:`switch_inline_query_chosen_chat`,
|
||||||
but gives no control over which chats can be selected.
|
but gives no control over which chats can be selected.
|
||||||
switch_inline_query_current_chat (:obj:`str`): Optional. If set, pressing the button will
|
switch_inline_query_current_chat (:obj:`str`): Optional. If set, pressing the button will
|
||||||
insert the bot's username and the specified inline query in the current chat's input
|
insert the bot's username and the specified inline query in the current chat's input
|
||||||
|
@ -208,7 +204,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||||
Note:
|
Note:
|
||||||
This type of button **must** always be the first button in the first row and can
|
This type of button **must** always be the first button in the first row and can
|
||||||
only be used in invoice messages.
|
only be used in invoice messages.
|
||||||
switch_inline_query_chosen_chat (:obj:`telegram.SwitchInlineQueryChosenChat`): Optional.
|
switch_inline_query_chosen_chat (:class:`telegram.SwitchInlineQueryChosenChat`): Optional.
|
||||||
If set, pressing the button will prompt the user to select one of their chats of the
|
If set, pressing the button will prompt the user to select one of their chats of the
|
||||||
specified type, open that chat and insert the bot's username and the specified inline
|
specified type, open that chat and insert the bot's username and the specified inline
|
||||||
query in the input field. Not supported for messages sent on behalf of a Telegram
|
query in the input field. Not supported for messages sent on behalf of a Telegram
|
||||||
|
|
|
@ -50,16 +50,14 @@ class InlineQueryResultGif(InlineQueryResult):
|
||||||
gif_width (:obj:`int`, optional): Width of the GIF.
|
gif_width (:obj:`int`, optional): Width of the GIF.
|
||||||
gif_height (:obj:`int`, optional): Height of the GIF.
|
gif_height (:obj:`int`, optional): Height of the GIF.
|
||||||
gif_duration (:obj:`int`, optional): Duration of the GIF in seconds.
|
gif_duration (:obj:`int`, optional): Duration of the GIF in seconds.
|
||||||
thumbnail_url (:obj:`str`, optional): URL of the static (JPEG or GIF) or animated (MPEG4)
|
thumbnail_url (:obj:`str`): URL of the static (JPEG or GIF) or animated (MPEG4)
|
||||||
thumbnail for the result.
|
thumbnail for the result.
|
||||||
|
|
||||||
Warning:
|
|
||||||
The Bot API does **not** define this as an optional argument. It is formally
|
|
||||||
optional for backwards compatibility with the deprecated :paramref:`thumb_url`.
|
|
||||||
If you pass neither :paramref:`thumbnail_url` nor :paramref:`thumb_url`,
|
|
||||||
:class:`ValueError` will be raised.
|
|
||||||
|
|
||||||
.. versionadded:: 20.2
|
.. versionadded:: 20.2
|
||||||
|
|
||||||
|
..versionchanged:: 20.5
|
||||||
|
|thumbnail_url_mandatory|
|
||||||
|
|
||||||
thumbnail_mime_type (:obj:`str`, optional): MIME type of the thumbnail, must be one of
|
thumbnail_mime_type (:obj:`str`, optional): MIME type of the thumbnail, must be one of
|
||||||
``'image/jpeg'``, ``'image/gif'``, or ``'video/mp4'``. Defaults to ``'image/jpeg'``.
|
``'image/jpeg'``, ``'image/gif'``, or ``'video/mp4'``. Defaults to ``'image/jpeg'``.
|
||||||
|
|
||||||
|
@ -82,10 +80,6 @@ class InlineQueryResultGif(InlineQueryResult):
|
||||||
|
|
||||||
.. versionadded:: 21.3
|
.. versionadded:: 21.3
|
||||||
|
|
||||||
Raises:
|
|
||||||
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
|
|
||||||
supplied or if both are supplied and are not equal.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.GIF`.
|
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.GIF`.
|
||||||
id (:obj:`str`): Unique identifier for this result,
|
id (:obj:`str`): Unique identifier for this result,
|
||||||
|
|
|
@ -51,16 +51,14 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
||||||
mpeg4_width (:obj:`int`, optional): Video width.
|
mpeg4_width (:obj:`int`, optional): Video width.
|
||||||
mpeg4_height (:obj:`int`, optional): Video height.
|
mpeg4_height (:obj:`int`, optional): Video height.
|
||||||
mpeg4_duration (:obj:`int`, optional): Video duration in seconds.
|
mpeg4_duration (:obj:`int`, optional): Video duration in seconds.
|
||||||
thumbnail_url (:obj:`str`, optional): URL of the static (JPEG or GIF) or animated (MPEG4)
|
thumbnail_url (:obj:`str`): URL of the static (JPEG or GIF) or animated (MPEG4)
|
||||||
thumbnail for the result.
|
thumbnail for the result.
|
||||||
|
|
||||||
Warning:
|
|
||||||
The Bot API does **not** define this as an optional argument. It is formally
|
|
||||||
optional for backwards compatibility with the deprecated :paramref:`thumb_url`.
|
|
||||||
If you pass neither :paramref:`thumbnail_url` nor :paramref:`thumb_url`,
|
|
||||||
:class:`ValueError` will be raised.
|
|
||||||
|
|
||||||
.. versionadded:: 20.2
|
.. versionadded:: 20.2
|
||||||
|
|
||||||
|
..versionchanged:: 20.5
|
||||||
|
|thumbnail_url_mandatory|
|
||||||
|
|
||||||
thumbnail_mime_type (:obj:`str`, optional): MIME type of the thumbnail, must be one of
|
thumbnail_mime_type (:obj:`str`, optional): MIME type of the thumbnail, must be one of
|
||||||
``'image/jpeg'``, ``'image/gif'``, or ``'video/mp4'``. Defaults to ``'image/jpeg'``.
|
``'image/jpeg'``, ``'image/gif'``, or ``'video/mp4'``. Defaults to ``'image/jpeg'``.
|
||||||
|
|
||||||
|
@ -83,9 +81,6 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
||||||
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
|
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
|
||||||
|
|
||||||
.. versionadded:: 21.3
|
.. versionadded:: 21.3
|
||||||
Raises:
|
|
||||||
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
|
|
||||||
supplied or if both are supplied and are not equal.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.MPEG4GIF`.
|
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.MPEG4GIF`.
|
||||||
|
|
|
@ -48,15 +48,13 @@ class InlineQueryResultPhoto(InlineQueryResult):
|
||||||
:tg-const:`telegram.InlineQueryResult.MAX_ID_LENGTH` Bytes.
|
:tg-const:`telegram.InlineQueryResult.MAX_ID_LENGTH` Bytes.
|
||||||
photo_url (:obj:`str`): A valid URL of the photo. Photo must be in JPEG format. Photo size
|
photo_url (:obj:`str`): A valid URL of the photo. Photo must be in JPEG format. Photo size
|
||||||
must not exceed 5MB.
|
must not exceed 5MB.
|
||||||
thumbnail_url (:obj:`str`, optional): URL of the thumbnail for the photo.
|
thumbnail_url (:obj:`str`): URL of the thumbnail for the photo.
|
||||||
|
|
||||||
Warning:
|
|
||||||
The Bot API does **not** define this as an optional argument. It is formally
|
|
||||||
optional for backwards compatibility with the deprecated :paramref:`thumb_url`.
|
|
||||||
If you pass neither :paramref:`thumbnail_url` nor :paramref:`thumb_url`,
|
|
||||||
:class:`ValueError` will be raised.
|
|
||||||
|
|
||||||
.. versionadded:: 20.2
|
.. versionadded:: 20.2
|
||||||
|
|
||||||
|
..versionchanged:: 20.5
|
||||||
|
|thumbnail_url_mandatory|
|
||||||
|
|
||||||
photo_width (:obj:`int`, optional): Width of the photo.
|
photo_width (:obj:`int`, optional): Width of the photo.
|
||||||
photo_height (:obj:`int`, optional): Height of the photo.
|
photo_height (:obj:`int`, optional): Height of the photo.
|
||||||
title (:obj:`str`, optional): Title for the result.
|
title (:obj:`str`, optional): Title for the result.
|
||||||
|
@ -78,10 +76,6 @@ class InlineQueryResultPhoto(InlineQueryResult):
|
||||||
|
|
||||||
.. versionadded:: 21.3
|
.. versionadded:: 21.3
|
||||||
|
|
||||||
Raises:
|
|
||||||
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
|
|
||||||
supplied or if both are supplied and are not equal.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.PHOTO`.
|
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.PHOTO`.
|
||||||
id (:obj:`str`): Unique identifier for this result,
|
id (:obj:`str`): Unique identifier for this result,
|
||||||
|
|
|
@ -55,20 +55,12 @@ class InlineQueryResultVideo(InlineQueryResult):
|
||||||
mime_type (:obj:`str`): Mime type of the content of video url, "text/html" or "video/mp4".
|
mime_type (:obj:`str`): Mime type of the content of video url, "text/html" or "video/mp4".
|
||||||
thumbnail_url (:obj:`str`, optional): URL of the thumbnail (JPEG only) for the video.
|
thumbnail_url (:obj:`str`, optional): URL of the thumbnail (JPEG only) for the video.
|
||||||
|
|
||||||
Warning:
|
|
||||||
The Bot API does **not** define this as an optional argument. It is formally
|
|
||||||
optional for backwards compatibility with the deprecated :paramref:`thumb_url`.
|
|
||||||
If you pass neither :paramref:`thumbnail_url` nor :paramref:`thumb_url`,
|
|
||||||
:class:`ValueError` will be raised.
|
|
||||||
|
|
||||||
.. versionadded:: 20.2
|
.. versionadded:: 20.2
|
||||||
title (:obj:`str`, optional): Title for the result.
|
|
||||||
|
|
||||||
Warning:
|
..versionchanged:: 20.5
|
||||||
The Bot API does **not** define this as an optional argument. It is formally
|
|thumbnail_url_mandatory|
|
||||||
optional to ensure backwards compatibility of :paramref:`thumbnail_url` with the
|
|
||||||
deprecated :paramref:`thumb_url`, which required that :paramref:`thumbnail_url`
|
title (:obj:`str`): Title for the result.
|
||||||
become optional. :class:`TypeError` will be raised if no ``title`` is passed.
|
|
||||||
caption (:obj:`str`, optional): Caption of the video to be sent,
|
caption (:obj:`str`, optional): Caption of the video to be sent,
|
||||||
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
|
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
|
||||||
parsing.
|
parsing.
|
||||||
|
@ -92,11 +84,6 @@ class InlineQueryResultVideo(InlineQueryResult):
|
||||||
|
|
||||||
.. versionadded:: 21.3
|
.. versionadded:: 21.3
|
||||||
|
|
||||||
Raises:
|
|
||||||
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
|
|
||||||
supplied or if both are supplied and are not equal.
|
|
||||||
:class:`TypeError`: If no :paramref:`title` is passed.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.VIDEO`.
|
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.VIDEO`.
|
||||||
id (:obj:`str`): Unique identifier for this result,
|
id (:obj:`str`): Unique identifier for this result,
|
||||||
|
|
|
@ -47,7 +47,7 @@ class InputInvoiceMessageContent(InputMessageContent):
|
||||||
payload (:obj:`str`): Bot-defined invoice payload.
|
payload (:obj:`str`): Bot-defined invoice payload.
|
||||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||||
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be displayed
|
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be displayed
|
||||||
to the user, use for your internal processes.
|
to the user, use it for your internal processes.
|
||||||
provider_token (:obj:`str`): Payment provider token, obtained via
|
provider_token (:obj:`str`): Payment provider token, obtained via
|
||||||
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in
|
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in
|
||||||
|tg_stars|.
|
|tg_stars|.
|
||||||
|
@ -115,7 +115,7 @@ class InputInvoiceMessageContent(InputMessageContent):
|
||||||
payload (:obj:`str`): Bot-defined invoice payload.
|
payload (:obj:`str`): Bot-defined invoice payload.
|
||||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||||
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be displayed
|
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be displayed
|
||||||
to the user, use for your internal processes.
|
to the user, use it for your internal processes.
|
||||||
provider_token (:obj:`str`): Payment provider token, obtained via
|
provider_token (:obj:`str`): Payment provider token, obtained via
|
||||||
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in `Telegram
|
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in `Telegram
|
||||||
Stars <https://t.me/BotNews/90>`_.
|
Stars <https://t.me/BotNews/90>`_.
|
||||||
|
|
|
@ -280,15 +280,14 @@ class Message(MaybeInaccessibleMessage):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message_id (:obj:`int`): Unique message identifier inside this chat.
|
message_id (:obj:`int`): Unique message identifier inside this chat.
|
||||||
from_user (:class:`telegram.User`, optional): Sender of the message; empty for messages
|
from_user (:class:`telegram.User`, optional): Sender of the message; may be empty for
|
||||||
sent to channels. For backward compatibility, this will contain a fake sender user in
|
messages sent to channels. For backward compatibility, if the message was sent on
|
||||||
non-channel chats, if the message was sent on behalf of a chat.
|
behalf of a chat, the field contains a fake sender user in non-channel chats.
|
||||||
sender_chat (:class:`telegram.Chat`, optional): Sender of the message, sent on behalf of a
|
sender_chat (:class:`telegram.Chat`, optional): Sender of the message when sent on behalf
|
||||||
chat. For example, the channel itself for channel posts, the supergroup itself for
|
of a chat. For example, the supergroup itself for messages sent by its anonymous
|
||||||
messages from anonymous group administrators, the linked channel for messages
|
administrators or a linked channel for messages automatically forwarded to the
|
||||||
automatically forwarded to the discussion group. For backward compatibility,
|
channel's discussion group. For backward compatibility, if the message was sent on
|
||||||
:attr:`from_user` contains a fake sender user in non-channel chats, if the message was
|
behalf of a chat, the field from contains a fake sender user in non-channel chats.
|
||||||
sent on behalf of a chat.
|
|
||||||
date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
|
date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
|
||||||
:class:`datetime.datetime`.
|
:class:`datetime.datetime`.
|
||||||
|
|
||||||
|
@ -570,36 +569,35 @@ class Message(MaybeInaccessibleMessage):
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
|
|
||||||
sender_business_bot (:obj:`telegram.User`, optional): The bot that actually sent the
|
sender_business_bot (:class:`telegram.User`, optional): The bot that actually sent the
|
||||||
message on behalf of the business account. Available only for outgoing messages sent
|
message on behalf of the business account. Available only for outgoing messages sent
|
||||||
on behalf of the connected business account.
|
on behalf of the connected business account.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
|
|
||||||
chat_background_set (:obj:`telegram.ChatBackground`, optional): Service message: chat
|
chat_background_set (:class:`telegram.ChatBackground`, optional): Service message: chat
|
||||||
background set.
|
background set.
|
||||||
|
|
||||||
.. versionadded:: 21.2
|
.. versionadded:: 21.2
|
||||||
paid_media (:obj:`telegram.PaidMediaInfo`, optional): Message contains paid media;
|
paid_media (:class:`telegram.PaidMediaInfo`, optional): Message contains paid media;
|
||||||
information about the paid media.
|
information about the paid media.
|
||||||
|
|
||||||
.. versionadded:: 21.4
|
.. versionadded:: 21.4
|
||||||
refunded_payment (:obj:`telegram.RefundedPayment`, optional): Message is a service message
|
refunded_payment (:class:`telegram.RefundedPayment`, optional): Message is a service
|
||||||
about a refunded payment, information about the payment.
|
message about a refunded payment, information about the payment.
|
||||||
|
|
||||||
.. versionadded:: 21.4
|
.. versionadded:: 21.4
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
message_id (:obj:`int`): Unique message identifier inside this chat.
|
message_id (:obj:`int`): Unique message identifier inside this chat.
|
||||||
from_user (:class:`telegram.User`): Optional. Sender of the message; empty for messages
|
from_user (:class:`telegram.User`): Optional. Sender of the message; may be empty for
|
||||||
sent to channels. For backward compatibility, this will contain a fake sender user in
|
messages sent to channels. For backward compatibility, if the message was sent on
|
||||||
non-channel chats, if the message was sent on behalf of a chat.
|
behalf of a chat, the field contains a fake sender user in non-channel chats.
|
||||||
sender_chat (:class:`telegram.Chat`): Optional. Sender of the message, sent on behalf of a
|
sender_chat (:class:`telegram.Chat`): Optional. Sender of the message when sent on behalf
|
||||||
chat. For example, the channel itself for channel posts, the supergroup itself for
|
of a chat. For example, the supergroup itself for messages sent by its anonymous
|
||||||
messages from anonymous group administrators, the linked channel for messages
|
administrators or a linked channel for messages automatically forwarded to the
|
||||||
automatically forwarded to the discussion group. For backward compatibility,
|
channel's discussion group. For backward compatibility, if the message was sent on
|
||||||
:attr:`from_user` contains a fake sender user in non-channel chats, if the message was
|
behalf of a chat, the field from contains a fake sender user in non-channel chats.
|
||||||
sent on behalf of a chat.
|
|
||||||
date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
|
date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
|
||||||
:class:`datetime.datetime`.
|
:class:`datetime.datetime`.
|
||||||
|
|
||||||
|
@ -897,22 +895,22 @@ class Message(MaybeInaccessibleMessage):
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
|
|
||||||
sender_business_bot (:obj:`telegram.User`): Optional. The bot that actually sent the
|
sender_business_bot (:class:`telegram.User`): Optional. The bot that actually sent the
|
||||||
message on behalf of the business account. Available only for outgoing messages sent
|
message on behalf of the business account. Available only for outgoing messages sent
|
||||||
on behalf of the connected business account.
|
on behalf of the connected business account.
|
||||||
|
|
||||||
.. versionadded:: 21.1
|
.. versionadded:: 21.1
|
||||||
|
|
||||||
chat_background_set (:obj:`telegram.ChatBackground`): Optional. Service message: chat
|
chat_background_set (:class:`telegram.ChatBackground`): Optional. Service message: chat
|
||||||
background set
|
background set
|
||||||
|
|
||||||
.. versionadded:: 21.2
|
.. versionadded:: 21.2
|
||||||
paid_media (:obj:`telegram.PaidMediaInfo`): Optional. Message contains paid media;
|
paid_media (:class:`telegram.PaidMediaInfo`): Optional. Message contains paid media;
|
||||||
information about the paid media.
|
information about the paid media.
|
||||||
|
|
||||||
.. versionadded:: 21.4
|
.. versionadded:: 21.4
|
||||||
refunded_payment (:obj:`telegram.RefundedPayment`): Optional. Message is a service message
|
refunded_payment (:class:`telegram.RefundedPayment`): Optional. Message is a service
|
||||||
about a refunded payment, information about the payment.
|
message about a refunded payment, information about the payment.
|
||||||
|
|
||||||
.. versionadded:: 21.4
|
.. versionadded:: 21.4
|
||||||
|
|
||||||
|
@ -4114,7 +4112,7 @@ class Message(MaybeInaccessibleMessage):
|
||||||
|
|
||||||
For the documentation of the arguments, please see :meth:`telegram.Bot.pin_chat_message`.
|
For the documentation of the arguments, please see :meth:`telegram.Bot.pin_chat_message`.
|
||||||
|
|
||||||
.. versionchanged:: NEXT.VERSION
|
.. versionchanged:: 21.5
|
||||||
Now also passes :attr:`business_connection_id` to
|
Now also passes :attr:`business_connection_id` to
|
||||||
:meth:`telegram.Bot.pin_chat_message`.
|
:meth:`telegram.Bot.pin_chat_message`.
|
||||||
|
|
||||||
|
@ -4154,7 +4152,7 @@ class Message(MaybeInaccessibleMessage):
|
||||||
|
|
||||||
For the documentation of the arguments, please see :meth:`telegram.Bot.unpin_chat_message`.
|
For the documentation of the arguments, please see :meth:`telegram.Bot.unpin_chat_message`.
|
||||||
|
|
||||||
.. versionchanged:: NEXT.VERSION
|
.. versionchanged:: 21.5
|
||||||
Now also passes :attr:`business_connection_id` to
|
Now also passes :attr:`business_connection_id` to
|
||||||
:meth:`telegram.Bot.pin_chat_message`.
|
:meth:`telegram.Bot.pin_chat_message`.
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import itertools
|
import itertools
|
||||||
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence
|
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence, Tuple, Union
|
||||||
|
|
||||||
from telegram import constants
|
from telegram import constants
|
||||||
from telegram._telegramobject import TelegramObject
|
from telegram._telegramobject import TelegramObject
|
||||||
|
@ -32,6 +32,8 @@ from telegram._utils.types import JSONDict
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from telegram import Bot
|
from telegram import Bot
|
||||||
|
|
||||||
|
_SEM = Sequence["MessageEntity"]
|
||||||
|
|
||||||
|
|
||||||
class MessageEntity(TelegramObject):
|
class MessageEntity(TelegramObject):
|
||||||
"""
|
"""
|
||||||
|
@ -146,9 +148,7 @@ class MessageEntity(TelegramObject):
|
||||||
return super().de_json(data=data, bot=bot)
|
return super().de_json(data=data, bot=bot)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def adjust_message_entities_to_utf_16(
|
def adjust_message_entities_to_utf_16(text: str, entities: _SEM) -> _SEM:
|
||||||
text: str, entities: Sequence["MessageEntity"]
|
|
||||||
) -> Sequence["MessageEntity"]:
|
|
||||||
"""Utility functionality for converting the offset and length of entities from
|
"""Utility functionality for converting the offset and length of entities from
|
||||||
Unicode (:obj:`str`) to UTF-16 (``utf-16-le`` encoded :obj:`bytes`).
|
Unicode (:obj:`str`) to UTF-16 (``utf-16-le`` encoded :obj:`bytes`).
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ class MessageEntity(TelegramObject):
|
||||||
text_slice = text[last_position:position]
|
text_slice = text[last_position:position]
|
||||||
accumulated_length += len(text_slice.encode(TextEncoding.UTF_16_LE)) // 2
|
accumulated_length += len(text_slice.encode(TextEncoding.UTF_16_LE)) // 2
|
||||||
position_translation[position] = accumulated_length
|
position_translation[position] = accumulated_length
|
||||||
# get the final output entites
|
# get the final output entities
|
||||||
out = []
|
out = []
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
translated_positions = position_translation[entity.offset]
|
translated_positions = position_translation[entity.offset]
|
||||||
|
@ -220,6 +220,143 @@ class MessageEntity(TelegramObject):
|
||||||
out.append(new_entity)
|
out.append(new_entity)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def shift_entities(by: Union[str, int], entities: _SEM) -> _SEM:
|
||||||
|
"""Utility functionality for shifting the offset of entities by a given amount.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
Shifting by an integer amount:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
text = "Hello, world!"
|
||||||
|
entities = [
|
||||||
|
MessageEntity(offset=0, length=5, type=MessageEntity.BOLD),
|
||||||
|
MessageEntity(offset=7, length=5, type=MessageEntity.ITALIC),
|
||||||
|
]
|
||||||
|
shifted_entities = MessageEntity.shift_entities(1, entities)
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=123,
|
||||||
|
text="!" + text,
|
||||||
|
entities=shifted_entities,
|
||||||
|
)
|
||||||
|
|
||||||
|
Shifting using a string:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
text = "Hello, world!"
|
||||||
|
prefix = "𝄢"
|
||||||
|
entities = [
|
||||||
|
MessageEntity(offset=0, length=5, type=MessageEntity.BOLD),
|
||||||
|
MessageEntity(offset=7, length=5, type=MessageEntity.ITALIC),
|
||||||
|
]
|
||||||
|
shifted_entities = MessageEntity.shift_entities(prefix, entities)
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=123,
|
||||||
|
text=prefix + text,
|
||||||
|
entities=shifted_entities,
|
||||||
|
)
|
||||||
|
|
||||||
|
Tip:
|
||||||
|
The :paramref:`entities` are *not* modified in place. The function returns a sequence
|
||||||
|
of new objects.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Args:
|
||||||
|
by (:obj:`str` | :obj:`int`): Either the amount to shift the offset by or
|
||||||
|
a string whose length will be used as the amount to shift the offset by. In this
|
||||||
|
case, UTF-16 encoding will be used to calculate the length.
|
||||||
|
entities (Sequence[:class:`telegram.MessageEntity`]): Sequence of entities
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Sequence[:class:`telegram.MessageEntity`]: Sequence of entities with the offset shifted
|
||||||
|
"""
|
||||||
|
effective_shift = by if isinstance(by, int) else len(by.encode("utf-16-le")) // 2
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for entity in entities:
|
||||||
|
new_entity = copy.copy(entity)
|
||||||
|
with new_entity._unfrozen():
|
||||||
|
new_entity.offset += effective_shift
|
||||||
|
out.append(new_entity)
|
||||||
|
return out
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def concatenate(
|
||||||
|
cls,
|
||||||
|
*args: Union[Tuple[str, _SEM], Tuple[str, _SEM, bool]],
|
||||||
|
) -> Tuple[str, _SEM]:
|
||||||
|
"""Utility functionality for concatenating two text along with their formatting entities.
|
||||||
|
|
||||||
|
Tip:
|
||||||
|
This function is useful for prefixing an already formatted text with a new text and its
|
||||||
|
formatting entities. In particular, it automatically correctly handles UTF-16 encoding.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
This example shows a callback function that can be used to add a prefix and suffix to
|
||||||
|
the message in a :class:`~telegram.ext.CallbackQueryHandler`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def prefix_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
prefix = "𠌕 bold 𝄢 italic underlined: 𝛙𝌢𑁍 | "
|
||||||
|
prefix_entities = [
|
||||||
|
MessageEntity(offset=2, length=4, type=MessageEntity.BOLD),
|
||||||
|
MessageEntity(offset=9, length=6, type=MessageEntity.ITALIC),
|
||||||
|
MessageEntity(offset=28, length=3, type=MessageEntity.UNDERLINE),
|
||||||
|
]
|
||||||
|
suffix = " | 𠌕 bold 𝄢 italic underlined: 𝛙𝌢𑁍"
|
||||||
|
suffix_entities = [
|
||||||
|
MessageEntity(offset=5, length=4, type=MessageEntity.BOLD),
|
||||||
|
MessageEntity(offset=12, length=6, type=MessageEntity.ITALIC),
|
||||||
|
MessageEntity(offset=31, length=3, type=MessageEntity.UNDERLINE),
|
||||||
|
]
|
||||||
|
|
||||||
|
message = update.effective_message
|
||||||
|
first = (prefix, prefix_entities, True)
|
||||||
|
second = (message.text, message.entities)
|
||||||
|
third = (suffix, suffix_entities, True)
|
||||||
|
|
||||||
|
new_text, new_entities = MessageEntity.concatenate(first, second, third)
|
||||||
|
await update.callback_query.edit_message_text(
|
||||||
|
text=new_text,
|
||||||
|
entities=new_entities,
|
||||||
|
)
|
||||||
|
|
||||||
|
Hint:
|
||||||
|
The entities are *not* modified in place. The function returns a
|
||||||
|
new sequence of objects.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*args (Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]] | \
|
||||||
|
Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`], :obj:`bool`]):
|
||||||
|
Arbitrary number of tuples containing the text and its entities to concatenate.
|
||||||
|
If the last element of the tuple is a :obj:`bool`, it is used to determine whether
|
||||||
|
to adjust the entities to UTF-16 via
|
||||||
|
:meth:`adjust_message_entities_to_utf_16`. UTF-16 adjustment is disabled by
|
||||||
|
default.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]]: The concatenated text
|
||||||
|
and its entities
|
||||||
|
"""
|
||||||
|
output_text = ""
|
||||||
|
output_entities: List[MessageEntity] = []
|
||||||
|
for arg in args:
|
||||||
|
text, entities = arg[0], arg[1]
|
||||||
|
|
||||||
|
if len(arg) > 2 and arg[2] is True:
|
||||||
|
entities = cls.adjust_message_entities_to_utf_16(text, entities)
|
||||||
|
|
||||||
|
output_entities.extend(cls.shift_entities(output_text, entities))
|
||||||
|
output_text += text
|
||||||
|
|
||||||
|
return output_text, output_entities
|
||||||
|
|
||||||
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
|
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
|
||||||
"""List[:obj:`str`]: A list of all available message entity types."""
|
"""List[:obj:`str`]: A list of all available message entity types."""
|
||||||
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
|
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
|
||||||
|
|
|
@ -112,7 +112,7 @@ class EncryptedCredentials(TelegramObject):
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
This object is decrypted only when originating from
|
This object is decrypted only when originating from
|
||||||
:obj:`telegram.PassportData.decrypted_credentials`.
|
:attr:`telegram.PassportData.decrypted_credentials`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data (:class:`telegram.Credentials` | :obj:`str`): Decrypted data with unique user's
|
data (:class:`telegram.Credentials` | :obj:`str`): Decrypted data with unique user's
|
||||||
|
|
|
@ -42,7 +42,7 @@ class EncryptedPassportElement(TelegramObject):
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
This object is decrypted only when originating from
|
This object is decrypted only when originating from
|
||||||
:obj:`telegram.PassportData.decrypted_data`.
|
:attr:`telegram.PassportData.decrypted_data`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
type (:obj:`str`): Element type. One of "personal_details", "passport", "driver_license",
|
type (:obj:`str`): Element type. One of "personal_details", "passport", "driver_license",
|
||||||
|
|
|
@ -203,7 +203,7 @@ class PassportFile(TelegramObject):
|
||||||
"""
|
"""
|
||||||
Wrapper over :meth:`telegram.Bot.get_file`. Will automatically assign the correct
|
Wrapper over :meth:`telegram.Bot.get_file`. Will automatically assign the correct
|
||||||
credentials to the returned :class:`telegram.File` if originating from
|
credentials to the returned :class:`telegram.File` if originating from
|
||||||
:obj:`telegram.PassportData.decrypted_data`.
|
:attr:`telegram.PassportData.decrypted_data`.
|
||||||
|
|
||||||
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
|
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ from datetime import datetime
|
||||||
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
|
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
|
||||||
|
|
||||||
from telegram import constants
|
from telegram import constants
|
||||||
|
from telegram._paidmedia import PaidMedia
|
||||||
from telegram._telegramobject import TelegramObject
|
from telegram._telegramobject import TelegramObject
|
||||||
from telegram._user import User
|
from telegram._user import User
|
||||||
from telegram._utils import enum
|
from telegram._utils import enum
|
||||||
|
@ -74,6 +75,17 @@ class RevenueWithdrawalState(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["RevenueWithdrawalState"]:
|
) -> Optional["RevenueWithdrawalState"]:
|
||||||
|
"""Converts JSON data to the appropriate :class:`RevenueWithdrawalState` object, i.e. takes
|
||||||
|
care of selecting the correct subclass.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (Dict[:obj:`str`, ...]): The JSON data.
|
||||||
|
bot (:class:`telegram.Bot`): The bot associated with this object.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The Telegram object.
|
||||||
|
|
||||||
|
"""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -150,6 +162,7 @@ class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["RevenueWithdrawalStateSucceeded"]:
|
) -> Optional["RevenueWithdrawalStateSucceeded"]:
|
||||||
|
"""See :meth:`telegram.RevenueWithdrawalState.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -260,13 +273,13 @@ class TransactionPartnerFragment(TransactionPartner):
|
||||||
.. versionadded:: 21.4
|
.. versionadded:: 21.4
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
withdrawal_state (:obj:`telegram.RevenueWithdrawalState`, optional): State of the
|
withdrawal_state (:class:`telegram.RevenueWithdrawalState`, optional): State of the
|
||||||
transaction if the transaction is outgoing.
|
transaction if the transaction is outgoing.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): The type of the transaction partner,
|
type (:obj:`str`): The type of the transaction partner,
|
||||||
always :tg-const:`telegram.TransactionPartner.FRAGMENT`.
|
always :tg-const:`telegram.TransactionPartner.FRAGMENT`.
|
||||||
withdrawal_state (:obj:`telegram.RevenueWithdrawalState`): Optional. State of the
|
withdrawal_state (:class:`telegram.RevenueWithdrawalState`): Optional. State of the
|
||||||
transaction if the transaction is outgoing.
|
transaction if the transaction is outgoing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -287,6 +300,7 @@ class TransactionPartnerFragment(TransactionPartner):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["TransactionPartnerFragment"]:
|
) -> Optional["TransactionPartnerFragment"]:
|
||||||
|
"""See :meth:`telegram.TransactionPartner.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -310,20 +324,33 @@ class TransactionPartnerUser(TransactionPartner):
|
||||||
Args:
|
Args:
|
||||||
user (:class:`telegram.User`): Information about the user.
|
user (:class:`telegram.User`): Information about the user.
|
||||||
invoice_payload (:obj:`str`, optional): Bot-specified invoice payload.
|
invoice_payload (:obj:`str`, optional): Bot-specified invoice payload.
|
||||||
|
paid_media (Sequence[:class:`telegram.PaidMedia`], optional): Information about the paid
|
||||||
|
media bought by the user.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): The type of the transaction partner,
|
type (:obj:`str`): The type of the transaction partner,
|
||||||
always :tg-const:`telegram.TransactionPartner.USER`.
|
always :tg-const:`telegram.TransactionPartner.USER`.
|
||||||
user (:class:`telegram.User`): Information about the user.
|
user (:class:`telegram.User`): Information about the user.
|
||||||
invoice_payload (:obj:`str`): Optional. Bot-specified invoice payload.
|
invoice_payload (:obj:`str`): Optional. Bot-specified invoice payload.
|
||||||
|
paid_media (Tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid
|
||||||
|
media bought by the user.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ("invoice_payload", "user")
|
__slots__ = (
|
||||||
|
"invoice_payload",
|
||||||
|
"paid_media",
|
||||||
|
"user",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
user: "User",
|
user: "User",
|
||||||
invoice_payload: Optional[str] = None,
|
invoice_payload: Optional[str] = None,
|
||||||
|
paid_media: Optional[Sequence[PaidMedia]] = None,
|
||||||
*,
|
*,
|
||||||
api_kwargs: Optional[JSONDict] = None,
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -332,6 +359,7 @@ class TransactionPartnerUser(TransactionPartner):
|
||||||
with self._unfrozen():
|
with self._unfrozen():
|
||||||
self.user: User = user
|
self.user: User = user
|
||||||
self.invoice_payload: Optional[str] = invoice_payload
|
self.invoice_payload: Optional[str] = invoice_payload
|
||||||
|
self.paid_media: Optional[Tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media)
|
||||||
self._id_attrs = (
|
self._id_attrs = (
|
||||||
self.type,
|
self.type,
|
||||||
self.user,
|
self.user,
|
||||||
|
@ -341,12 +369,14 @@ class TransactionPartnerUser(TransactionPartner):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["TransactionPartnerUser"]:
|
) -> Optional["TransactionPartnerUser"]:
|
||||||
|
"""See :meth:`telegram.TransactionPartner.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
data["user"] = User.de_json(data.get("user"), bot)
|
data["user"] = User.de_json(data.get("user"), bot)
|
||||||
|
data["paid_media"] = PaidMedia.de_list(data.get("paid_media"), bot=bot)
|
||||||
|
|
||||||
return super().de_json(data=data, bot=bot) # type: ignore[return-value]
|
return super().de_json(data=data, bot=bot) # type: ignore[return-value]
|
||||||
|
|
||||||
|
@ -452,6 +482,7 @@ class StarTransaction(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["StarTransaction"]:
|
) -> Optional["StarTransaction"]:
|
||||||
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -498,6 +529,7 @@ class StarTransactions(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["StarTransactions"]:
|
) -> Optional["StarTransactions"]:
|
||||||
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
# You should have received a copy of the GNU Lesser Public License
|
# You should have received a copy of the GNU Lesser Public License
|
||||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||||
"""This module contains objects that represents a Telegram ReactionType."""
|
"""This module contains objects that represents a Telegram ReactionType."""
|
||||||
from typing import TYPE_CHECKING, Final, Literal, Optional, Union
|
|
||||||
|
from typing import TYPE_CHECKING, Dict, Final, Literal, Optional, Type, Union
|
||||||
|
|
||||||
from telegram import constants
|
from telegram import constants
|
||||||
from telegram._telegramobject import TelegramObject
|
from telegram._telegramobject import TelegramObject
|
||||||
|
@ -30,16 +31,22 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
class ReactionType(TelegramObject):
|
class ReactionType(TelegramObject):
|
||||||
"""Base class for Telegram ReactionType Objects.
|
"""Base class for Telegram ReactionType Objects.
|
||||||
There exist :class:`telegram.ReactionTypeEmoji` and :class:`telegram.ReactionTypeCustomEmoji`.
|
There exist :class:`telegram.ReactionTypeEmoji`, :class:`telegram.ReactionTypeCustomEmoji`
|
||||||
|
and :class:`telegram.ReactionTypePaid`.
|
||||||
|
|
||||||
.. versionadded:: 20.8
|
.. versionadded:: 20.8
|
||||||
|
.. versionchanged:: 21.5
|
||||||
|
|
||||||
|
Added paid reaction.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
type (:obj:`str`): Type of the reaction. Can be
|
type (:obj:`str`): Type of the reaction. Can be
|
||||||
:attr:`~telegram.ReactionType.EMOJI` or :attr:`~telegram.ReactionType.CUSTOM_EMOJI`.
|
:attr:`~telegram.ReactionType.EMOJI`, :attr:`~telegram.ReactionType.CUSTOM_EMOJI` or
|
||||||
|
:attr:`~telegram.ReactionType.PAID`.
|
||||||
Attributes:
|
Attributes:
|
||||||
type (:obj:`str`): Type of the reaction. Can be
|
type (:obj:`str`): Type of the reaction. Can be
|
||||||
:attr:`~telegram.ReactionType.EMOJI` or :attr:`~telegram.ReactionType.CUSTOM_EMOJI`.
|
:attr:`~telegram.ReactionType.EMOJI`, :attr:`~telegram.ReactionType.CUSTOM_EMOJI` or
|
||||||
|
:attr:`~telegram.ReactionType.PAID`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -49,11 +56,16 @@ class ReactionType(TelegramObject):
|
||||||
""":const:`telegram.constants.ReactionType.EMOJI`"""
|
""":const:`telegram.constants.ReactionType.EMOJI`"""
|
||||||
CUSTOM_EMOJI: Final[constants.ReactionType] = constants.ReactionType.CUSTOM_EMOJI
|
CUSTOM_EMOJI: Final[constants.ReactionType] = constants.ReactionType.CUSTOM_EMOJI
|
||||||
""":const:`telegram.constants.ReactionType.CUSTOM_EMOJI`"""
|
""":const:`telegram.constants.ReactionType.CUSTOM_EMOJI`"""
|
||||||
|
PAID: Final[constants.ReactionType] = constants.ReactionType.PAID
|
||||||
|
""":const:`telegram.constants.ReactionType.PAID`
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
type: Union[ # pylint: disable=redefined-builtin
|
type: Union[ # pylint: disable=redefined-builtin
|
||||||
Literal["emoji", "custom_emoji"], constants.ReactionType
|
Literal["emoji", "custom_emoji", "paid"], constants.ReactionType
|
||||||
],
|
],
|
||||||
*,
|
*,
|
||||||
api_kwargs: Optional[JSONDict] = None,
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
@ -71,14 +83,20 @@ class ReactionType(TelegramObject):
|
||||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if not data:
|
if data is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if cls is ReactionType and data.get("type") in [cls.EMOJI, cls.CUSTOM_EMOJI]:
|
if not data and cls is ReactionType:
|
||||||
reaction_type = data.pop("type")
|
return None
|
||||||
if reaction_type == cls.EMOJI:
|
|
||||||
return ReactionTypeEmoji.de_json(data=data, bot=bot)
|
_class_mapping: Dict[str, Type[ReactionType]] = {
|
||||||
return ReactionTypeCustomEmoji.de_json(data=data, bot=bot)
|
cls.EMOJI: ReactionTypeEmoji,
|
||||||
|
cls.CUSTOM_EMOJI: ReactionTypeCustomEmoji,
|
||||||
|
cls.PAID: ReactionTypePaid,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cls is ReactionType and data.get("type") in _class_mapping:
|
||||||
|
return _class_mapping[data.pop("type")].de_json(data, bot)
|
||||||
|
|
||||||
return super().de_json(data=data, bot=bot)
|
return super().de_json(data=data, bot=bot)
|
||||||
|
|
||||||
|
@ -152,6 +170,24 @@ class ReactionTypeCustomEmoji(ReactionType):
|
||||||
self._id_attrs = (self.custom_emoji_id,)
|
self._id_attrs = (self.custom_emoji_id,)
|
||||||
|
|
||||||
|
|
||||||
|
class ReactionTypePaid(ReactionType):
|
||||||
|
"""
|
||||||
|
The reaction is paid.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (:obj:`str`): Type of the reaction,
|
||||||
|
always :tg-const:`telegram.ReactionType.PAID`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, *, api_kwargs: Optional[JSONDict] = None):
|
||||||
|
super().__init__(type=ReactionType.PAID, api_kwargs=api_kwargs)
|
||||||
|
self._freeze()
|
||||||
|
|
||||||
|
|
||||||
class ReactionCount(TelegramObject):
|
class ReactionCount(TelegramObject):
|
||||||
"""This class represents a reaction added to a message along with the number of times it was
|
"""This class represents a reaction added to a message along with the number of times it was
|
||||||
added.
|
added.
|
||||||
|
|
|
@ -250,7 +250,7 @@ class ExternalReplyInfo(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["ExternalReplyInfo"]:
|
) -> Optional["ExternalReplyInfo"]:
|
||||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -299,7 +299,8 @@ class TextQuote(TelegramObject):
|
||||||
message.
|
message.
|
||||||
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
|
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
|
||||||
units as specified by the sender.
|
units as specified by the sender.
|
||||||
entities (Sequence[:obj:`telegram.MessageEntity`], optional): Special entities that appear
|
entities (Sequence[:class:`telegram.MessageEntity`], optional): Special entities that
|
||||||
|
appear
|
||||||
in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and
|
in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and
|
||||||
custom_emoji entities are kept in quotes.
|
custom_emoji entities are kept in quotes.
|
||||||
is_manual (:obj:`bool`, optional): :obj:`True`, if the quote was chosen manually by the
|
is_manual (:obj:`bool`, optional): :obj:`True`, if the quote was chosen manually by the
|
||||||
|
@ -310,7 +311,7 @@ class TextQuote(TelegramObject):
|
||||||
message.
|
message.
|
||||||
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
|
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
|
||||||
units as specified by the sender.
|
units as specified by the sender.
|
||||||
entities (Tuple[:obj:`telegram.MessageEntity`]): Optional. Special entities that appear
|
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that appear
|
||||||
in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and
|
in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and
|
||||||
custom_emoji entities are kept in quotes.
|
custom_emoji entities are kept in quotes.
|
||||||
is_manual (:obj:`bool`): Optional. :obj:`True`, if the quote was chosen manually by the
|
is_manual (:obj:`bool`): Optional. :obj:`True`, if the quote was chosen manually by the
|
||||||
|
@ -351,7 +352,7 @@ class TextQuote(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["TextQuote"]:
|
) -> Optional["TextQuote"]:
|
||||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -387,7 +388,8 @@ class ReplyParameters(TelegramObject):
|
||||||
quote_parse_mode (:obj:`str`, optional): Mode for parsing entities in the quote. See
|
quote_parse_mode (:obj:`str`, optional): Mode for parsing entities in the quote. See
|
||||||
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
|
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
|
||||||
more details.
|
more details.
|
||||||
quote_entities (Sequence[:obj:`telegram.MessageEntity`], optional): A JSON-serialized list
|
quote_entities (Sequence[:class:`telegram.MessageEntity`], optional): A JSON-serialized
|
||||||
|
list
|
||||||
of special entities that appear in the quote. It can be specified instead of
|
of special entities that appear in the quote. It can be specified instead of
|
||||||
:paramref:`quote_parse_mode`.
|
:paramref:`quote_parse_mode`.
|
||||||
quote_position (:obj:`int`, optional): Position of the quote in the original message in
|
quote_position (:obj:`int`, optional): Position of the quote in the original message in
|
||||||
|
@ -409,8 +411,8 @@ class ReplyParameters(TelegramObject):
|
||||||
quote_parse_mode (:obj:`str`): Optional. Mode for parsing entities in the quote. See
|
quote_parse_mode (:obj:`str`): Optional. Mode for parsing entities in the quote. See
|
||||||
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
|
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
|
||||||
more details.
|
more details.
|
||||||
quote_entities (Tuple[:obj:`telegram.MessageEntity`]): Optional. A JSON-serialized list of
|
quote_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. A JSON-serialized list
|
||||||
special entities that appear in the quote. It can be specified instead of
|
of special entities that appear in the quote. It can be specified instead of
|
||||||
:paramref:`quote_parse_mode`.
|
:paramref:`quote_parse_mode`.
|
||||||
quote_position (:obj:`int`): Optional. Position of the quote in the original message in
|
quote_position (:obj:`int`): Optional. Position of the quote in the original message in
|
||||||
UTF-16 code units.
|
UTF-16 code units.
|
||||||
|
@ -458,7 +460,7 @@ class ReplyParameters(TelegramObject):
|
||||||
def de_json(
|
def de_json(
|
||||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||||
) -> Optional["ReplyParameters"]:
|
) -> Optional["ReplyParameters"]:
|
||||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||||
data = cls._parse_data(data)
|
data = cls._parse_data(data)
|
||||||
|
|
||||||
if data is None:
|
if data is None:
|
||||||
|
|
|
@ -354,7 +354,7 @@ class TelegramObject:
|
||||||
memodict (:obj:`dict`): A dictionary that maps objects to their copies.
|
memodict (:obj:`dict`): A dictionary that maps objects to their copies.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`telegram.TelegramObject`: The copied object.
|
:class:`telegram.TelegramObject`: The copied object.
|
||||||
"""
|
"""
|
||||||
bot = self._bot # Save bot so we can set it after copying
|
bot = self._bot # Save bot so we can set it after copying
|
||||||
self.set_bot(None) # set to None so it is not deepcopied
|
self.set_bot(None) # set to None so it is not deepcopied
|
||||||
|
|
|
@ -100,7 +100,7 @@ class User(TelegramObject):
|
||||||
has_main_web_app (:obj:`bool`, optional): :obj:`True`, if the bot has the main Web App.
|
has_main_web_app (:obj:`bool`, optional): :obj:`True`, if the bot has the main Web App.
|
||||||
Returned only in :meth:`telegram.Bot.get_me`.
|
Returned only in :meth:`telegram.Bot.get_me`.
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
id (:obj:`int`): Unique identifier for this user or bot.
|
id (:obj:`int`): Unique identifier for this user or bot.
|
||||||
|
@ -131,7 +131,7 @@ class User(TelegramObject):
|
||||||
has_main_web_app (:obj:`bool`) Optional. :obj:`True`, if the bot has the main Web App.
|
has_main_web_app (:obj:`bool`) Optional. :obj:`True`, if the bot has the main Web App.
|
||||||
Returned only in :meth:`telegram.Bot.get_me`.
|
Returned only in :meth:`telegram.Bot.get_me`.
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
.. |user_chat_id_note| replace:: This shortcuts build on the assumption that :attr:`User.id`
|
.. |user_chat_id_note| replace:: This shortcuts build on the assumption that :attr:`User.id`
|
||||||
coincides with the :attr:`Chat.id` of the private chat with the user. This has been the
|
coincides with the :attr:`Chat.id` of the private chat with the user. This has been the
|
||||||
|
|
|
@ -33,7 +33,7 @@ from telegram._utils.enum import StringEnum
|
||||||
class TextEncoding(StringEnum):
|
class TextEncoding(StringEnum):
|
||||||
"""This enum contains encoding schemes for text.
|
"""This enum contains encoding schemes for text.
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
|
@ -51,6 +51,6 @@ class Version(NamedTuple):
|
||||||
|
|
||||||
|
|
||||||
__version_info__: Final[Version] = Version(
|
__version_info__: Final[Version] = Version(
|
||||||
major=21, minor=4, micro=0, releaselevel="final", serial=0
|
major=21, minor=5, micro=0, releaselevel="final", serial=0
|
||||||
)
|
)
|
||||||
__version__: Final[str] = str(__version_info__)
|
__version__: Final[str] = str(__version_info__)
|
||||||
|
|
|
@ -54,6 +54,7 @@ __all__ = [
|
||||||
"ChatLimit",
|
"ChatLimit",
|
||||||
"ChatMemberStatus",
|
"ChatMemberStatus",
|
||||||
"ChatPhotoSize",
|
"ChatPhotoSize",
|
||||||
|
"ChatSubscriptionLimit",
|
||||||
"ChatType",
|
"ChatType",
|
||||||
"ContactLimit",
|
"ContactLimit",
|
||||||
"CustomEmojiStickerLimit",
|
"CustomEmojiStickerLimit",
|
||||||
|
@ -151,7 +152,7 @@ class _AccentColor(NamedTuple):
|
||||||
#: :data:`telegram.__bot_api_version_info__`.
|
#: :data:`telegram.__bot_api_version_info__`.
|
||||||
#:
|
#:
|
||||||
#: .. versionadded:: 20.0
|
#: .. versionadded:: 20.0
|
||||||
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=8)
|
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=9)
|
||||||
#: :obj:`str`: Telegram Bot API
|
#: :obj:`str`: Telegram Bot API
|
||||||
#: version supported by this version of `python-telegram-bot`. Also available as
|
#: version supported by this version of `python-telegram-bot`. Also available as
|
||||||
#: :data:`telegram.__bot_api_version__`.
|
#: :data:`telegram.__bot_api_version__`.
|
||||||
|
@ -2903,6 +2904,11 @@ class ReactionType(StringEnum):
|
||||||
""":obj:`str`: A :class:`telegram.ReactionType` with a normal emoji."""
|
""":obj:`str`: A :class:`telegram.ReactionType` with a normal emoji."""
|
||||||
CUSTOM_EMOJI = "custom_emoji"
|
CUSTOM_EMOJI = "custom_emoji"
|
||||||
""":obj:`str`: A :class:`telegram.ReactionType` with a custom emoji."""
|
""":obj:`str`: A :class:`telegram.ReactionType` with a custom emoji."""
|
||||||
|
PAID = "paid"
|
||||||
|
""":obj:`str`: A :class:`telegram.ReactionType` with a paid reaction.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ReactionEmoji(StringEnum):
|
class ReactionEmoji(StringEnum):
|
||||||
|
@ -3096,3 +3102,22 @@ class BackgroundFillType(StringEnum):
|
||||||
""":obj:`str`: A :class:`telegram.BackgroundFill` with gradient fill."""
|
""":obj:`str`: A :class:`telegram.BackgroundFill` with gradient fill."""
|
||||||
FREEFORM_GRADIENT = "freeform_gradient"
|
FREEFORM_GRADIENT = "freeform_gradient"
|
||||||
""":obj:`str`: A :class:`telegram.BackgroundFill` with freeform_gradient fill."""
|
""":obj:`str`: A :class:`telegram.BackgroundFill` with freeform_gradient fill."""
|
||||||
|
|
||||||
|
|
||||||
|
class ChatSubscriptionLimit(IntEnum):
|
||||||
|
"""This enum contains limitations for
|
||||||
|
:paramref:`telegram.Bot.create_chat_subscription_invite_link.subscription_period` and
|
||||||
|
:paramref:`telegram.Bot.create_chat_subscription_invite_link.subscription_price`.
|
||||||
|
The enum members of this enumeration are instances of :class:`int` and can be treated as such.
|
||||||
|
|
||||||
|
.. versionadded:: 21.5
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
SUBSCRIPTION_PERIOD = 2592000
|
||||||
|
""":obj:`int`: The number of seconds the subscription will be active."""
|
||||||
|
MIN_PRICE = 1
|
||||||
|
""":obj:`int`: Amount of stars a user pays, minimum amount the subscription can be set to."""
|
||||||
|
MAX_PRICE = 2500
|
||||||
|
""":obj:`int`: Amount of stars a user pays, maximum amount the subscription can be set to."""
|
||||||
|
|
|
@ -4234,6 +4234,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||||
reply_parameters: Optional["ReplyParameters"] = None,
|
reply_parameters: Optional["ReplyParameters"] = None,
|
||||||
reply_markup: Optional[ReplyMarkup] = None,
|
reply_markup: Optional[ReplyMarkup] = None,
|
||||||
|
business_connection_id: Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||||
reply_to_message_id: Optional[int] = None,
|
reply_to_message_id: Optional[int] = None,
|
||||||
|
@ -4263,6 +4264,57 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||||
connect_timeout=connect_timeout,
|
connect_timeout=connect_timeout,
|
||||||
pool_timeout=pool_timeout,
|
pool_timeout=pool_timeout,
|
||||||
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||||
|
business_connection_id=business_connection_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def create_chat_subscription_invite_link(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
subscription_period: int,
|
||||||
|
subscription_price: int,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
rate_limit_args: Optional[RLARGS] = None,
|
||||||
|
) -> ChatInviteLink:
|
||||||
|
return await super().create_chat_subscription_invite_link(
|
||||||
|
chat_id=chat_id,
|
||||||
|
subscription_period=subscription_period,
|
||||||
|
subscription_price=subscription_price,
|
||||||
|
name=name,
|
||||||
|
read_timeout=read_timeout,
|
||||||
|
write_timeout=write_timeout,
|
||||||
|
connect_timeout=connect_timeout,
|
||||||
|
pool_timeout=pool_timeout,
|
||||||
|
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def edit_chat_subscription_invite_link(
|
||||||
|
self,
|
||||||
|
chat_id: Union[str, int],
|
||||||
|
invite_link: Union[str, "ChatInviteLink"],
|
||||||
|
name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||||
|
api_kwargs: Optional[JSONDict] = None,
|
||||||
|
rate_limit_args: Optional[RLARGS] = None,
|
||||||
|
) -> ChatInviteLink:
|
||||||
|
return await super().edit_chat_subscription_invite_link(
|
||||||
|
chat_id=chat_id,
|
||||||
|
invite_link=invite_link,
|
||||||
|
name=name,
|
||||||
|
read_timeout=read_timeout,
|
||||||
|
write_timeout=write_timeout,
|
||||||
|
connect_timeout=connect_timeout,
|
||||||
|
pool_timeout=pool_timeout,
|
||||||
|
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||||
)
|
)
|
||||||
|
|
||||||
# updated camelCase aliases
|
# updated camelCase aliases
|
||||||
|
@ -4388,4 +4440,6 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||||
replaceStickerInSet = replace_sticker_in_set
|
replaceStickerInSet = replace_sticker_in_set
|
||||||
refundStarPayment = refund_star_payment
|
refundStarPayment = refund_star_payment
|
||||||
getStarTransactions = get_star_transactions
|
getStarTransactions = get_star_transactions
|
||||||
|
createChatSubscriptionInviteLink = create_chat_subscription_invite_link
|
||||||
|
editChatSubscriptionInviteLink = edit_chat_subscription_invite_link
|
||||||
sendPaidMedia = send_paid_media
|
sendPaidMedia = send_paid_media
|
||||||
|
|
|
@ -58,7 +58,7 @@ class CallbackQueryHandler(BaseHandler[Update, CCT]):
|
||||||
`~telegram.CallbackQuery.game_short_name` or :attr:`~telegram.CallbackQuery.data`
|
`~telegram.CallbackQuery.game_short_name` or :attr:`~telegram.CallbackQuery.data`
|
||||||
matching the defined pattern will be handled
|
matching the defined pattern will be handled
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
|
|
||||||
Warning:
|
Warning:
|
||||||
When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom
|
When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom
|
||||||
|
@ -100,7 +100,7 @@ class CallbackQueryHandler(BaseHandler[Update, CCT]):
|
||||||
:attr:`telegram.CallbackQuery.game_short_name` to determine if an update should be
|
:attr:`telegram.CallbackQuery.game_short_name` to determine if an update should be
|
||||||
handled by this handler.
|
handled by this handler.
|
||||||
|
|
||||||
.. versionadded:: NEXT.VERSION
|
.. versionadded:: 21.5
|
||||||
block (:obj:`bool`, optional): Determines whether the return value of the callback should
|
block (:obj:`bool`, optional): Determines whether the return value of the callback should
|
||||||
be awaited before processing the next handler in
|
be awaited before processing the next handler in
|
||||||
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
|
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
|
||||||
|
|
|
@ -763,7 +763,6 @@ class Updater(AsyncContextManager["Updater"]):
|
||||||
_LOGGER.exception("Invalid token; aborting")
|
_LOGGER.exception("Invalid token; aborting")
|
||||||
raise
|
raise
|
||||||
except TelegramError as telegram_exc:
|
except TelegramError as telegram_exc:
|
||||||
_LOGGER.exception("Error while %s:", description)
|
|
||||||
on_err_cb(telegram_exc)
|
on_err_cb(telegram_exc)
|
||||||
|
|
||||||
# increase waiting times on subsequent errors up to 30secs
|
# increase waiting times on subsequent errors up to 30secs
|
||||||
|
|
|
@ -302,7 +302,7 @@ class BaseFilter:
|
||||||
|
|
||||||
class MessageFilter(BaseFilter):
|
class MessageFilter(BaseFilter):
|
||||||
"""Base class for all Message Filters. In contrast to :class:`UpdateFilter`, the object passed
|
"""Base class for all Message Filters. In contrast to :class:`UpdateFilter`, the object passed
|
||||||
to :meth:`filter` is :obj:`telegram.Update.effective_message`.
|
to :meth:`filter` is :attr:`telegram.Update.effective_message`.
|
||||||
|
|
||||||
Please see :class:`BaseFilter` for details on how to create custom filters.
|
Please see :class:`BaseFilter` for details on how to create custom filters.
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ class RequestData:
|
||||||
def multipart_data(self) -> UploadFileDict:
|
def multipart_data(self) -> UploadFileDict:
|
||||||
"""Gives the files contained in this object as mapping of part name to encoded content.
|
"""Gives the files contained in this object as mapping of part name to encoded content.
|
||||||
|
|
||||||
.. versionchanged:: NEXT.VERSION
|
.. versionchanged:: 21.5
|
||||||
Content may now be a file handle.
|
Content may now be a file handle.
|
||||||
"""
|
"""
|
||||||
multipart_data: UploadFileDict = {}
|
multipart_data: UploadFileDict = {}
|
||||||
|
|
|
@ -79,7 +79,7 @@ class RequestParameter:
|
||||||
def multipart_data(self) -> Optional[UploadFileDict]:
|
def multipart_data(self) -> Optional[UploadFileDict]:
|
||||||
"""A dict with the file data to upload, if any.
|
"""A dict with the file data to upload, if any.
|
||||||
|
|
||||||
.. versionchanged:: NEXT.VERSION
|
.. versionchanged:: 21.5
|
||||||
Content may now be a file handle.
|
Content may now be a file handle.
|
||||||
"""
|
"""
|
||||||
if not self.input_files:
|
if not self.input_files:
|
||||||
|
|
|
@ -51,7 +51,7 @@ async def animation(bot, chat_id):
|
||||||
).animation
|
).animation
|
||||||
|
|
||||||
|
|
||||||
class TestAnimationBase:
|
class AnimationTestBase:
|
||||||
animation_file_id = "CgADAQADngIAAuyVeEez0xRovKi9VAI"
|
animation_file_id = "CgADAQADngIAAuyVeEez0xRovKi9VAI"
|
||||||
animation_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
animation_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
width = 320
|
width = 320
|
||||||
|
@ -66,7 +66,7 @@ class TestAnimationBase:
|
||||||
caption = "Test *animation*"
|
caption = "Test *animation*"
|
||||||
|
|
||||||
|
|
||||||
class TestAnimationWithoutRequest(TestAnimationBase):
|
class TestAnimationWithoutRequest(AnimationTestBase):
|
||||||
def test_slot_behaviour(self, animation):
|
def test_slot_behaviour(self, animation):
|
||||||
for attr in animation.__slots__:
|
for attr in animation.__slots__:
|
||||||
assert getattr(animation, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(animation, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -219,7 +219,7 @@ class TestAnimationWithoutRequest(TestAnimationBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestAnimationWithRequest(TestAnimationBase):
|
class TestAnimationWithRequest(AnimationTestBase):
|
||||||
async def test_send_all_args(self, bot, chat_id, animation_file, animation, thumb_file):
|
async def test_send_all_args(self, bot, chat_id, animation_file, animation, thumb_file):
|
||||||
message = await bot.send_animation(
|
message = await bot.send_animation(
|
||||||
chat_id,
|
chat_id,
|
||||||
|
|
|
@ -49,7 +49,7 @@ async def audio(bot, chat_id):
|
||||||
return (await bot.send_audio(chat_id, audio=f, read_timeout=50, thumbnail=thumb)).audio
|
return (await bot.send_audio(chat_id, audio=f, read_timeout=50, thumbnail=thumb)).audio
|
||||||
|
|
||||||
|
|
||||||
class TestAudioBase:
|
class AudioTestBase:
|
||||||
caption = "Test *audio*"
|
caption = "Test *audio*"
|
||||||
performer = "Leandro Toledo"
|
performer = "Leandro Toledo"
|
||||||
title = "Teste"
|
title = "Teste"
|
||||||
|
@ -67,7 +67,7 @@ class TestAudioBase:
|
||||||
audio_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
audio_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
|
|
||||||
|
|
||||||
class TestAudioWithoutRequest(TestAudioBase):
|
class TestAudioWithoutRequest(AudioTestBase):
|
||||||
def test_slot_behaviour(self, audio):
|
def test_slot_behaviour(self, audio):
|
||||||
for attr in audio.__slots__:
|
for attr in audio.__slots__:
|
||||||
assert getattr(audio, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(audio, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -222,7 +222,7 @@ class TestAudioWithoutRequest(TestAudioBase):
|
||||||
await default_bot.send_audio(chat_id, audio, reply_parameters=ReplyParameters(**kwargs))
|
await default_bot.send_audio(chat_id, audio, reply_parameters=ReplyParameters(**kwargs))
|
||||||
|
|
||||||
|
|
||||||
class TestAudioWithRequest(TestAudioBase):
|
class TestAudioWithRequest(AudioTestBase):
|
||||||
async def test_send_all_args(self, bot, chat_id, audio_file, thumb_file):
|
async def test_send_all_args(self, bot, chat_id, audio_file, thumb_file):
|
||||||
message = await bot.send_audio(
|
message = await bot.send_audio(
|
||||||
chat_id,
|
chat_id,
|
||||||
|
|
|
@ -52,7 +52,7 @@ async def chat_photo(bot, super_group_id):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestChatPhotoBase:
|
class ChatPhotoTestBase:
|
||||||
chatphoto_small_file_id = "smallCgADAQADngIAAuyVeEez0xRovKi9VAI"
|
chatphoto_small_file_id = "smallCgADAQADngIAAuyVeEez0xRovKi9VAI"
|
||||||
chatphoto_big_file_id = "bigCgADAQADngIAAuyVeEez0xRovKi9VAI"
|
chatphoto_big_file_id = "bigCgADAQADngIAAuyVeEez0xRovKi9VAI"
|
||||||
chatphoto_small_file_unique_id = "smalladc3145fd2e84d95b64d68eaa22aa33e"
|
chatphoto_small_file_unique_id = "smalladc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
|
@ -60,7 +60,7 @@ class TestChatPhotoBase:
|
||||||
chatphoto_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.jpg"
|
chatphoto_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.jpg"
|
||||||
|
|
||||||
|
|
||||||
class TestChatPhotoWithoutRequest(TestChatPhotoBase):
|
class TestChatPhotoWithoutRequest(ChatPhotoTestBase):
|
||||||
def test_slot_behaviour(self, chat_photo):
|
def test_slot_behaviour(self, chat_photo):
|
||||||
for attr in chat_photo.__slots__:
|
for attr in chat_photo.__slots__:
|
||||||
assert getattr(chat_photo, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(chat_photo, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
|
|
@ -32,21 +32,21 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def contact():
|
def contact():
|
||||||
return Contact(
|
return Contact(
|
||||||
TestContactBase.phone_number,
|
ContactTestBase.phone_number,
|
||||||
TestContactBase.first_name,
|
ContactTestBase.first_name,
|
||||||
TestContactBase.last_name,
|
ContactTestBase.last_name,
|
||||||
TestContactBase.user_id,
|
ContactTestBase.user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestContactBase:
|
class ContactTestBase:
|
||||||
phone_number = "+11234567890"
|
phone_number = "+11234567890"
|
||||||
first_name = "Leandro"
|
first_name = "Leandro"
|
||||||
last_name = "Toledo"
|
last_name = "Toledo"
|
||||||
user_id = 23
|
user_id = 23
|
||||||
|
|
||||||
|
|
||||||
class TestContactWithoutRequest(TestContactBase):
|
class TestContactWithoutRequest(ContactTestBase):
|
||||||
def test_slot_behaviour(self, contact):
|
def test_slot_behaviour(self, contact):
|
||||||
for attr in contact.__slots__:
|
for attr in contact.__slots__:
|
||||||
assert getattr(contact, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(contact, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -156,7 +156,7 @@ class TestContactWithoutRequest(TestContactBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestContactWithRequest(TestContactBase):
|
class TestContactWithRequest(ContactTestBase):
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("default_bot", "custom"),
|
("default_bot", "custom"),
|
||||||
[
|
[
|
||||||
|
|
|
@ -49,7 +49,7 @@ async def document(bot, chat_id):
|
||||||
return (await bot.send_document(chat_id, document=f, read_timeout=50)).document
|
return (await bot.send_document(chat_id, document=f, read_timeout=50)).document
|
||||||
|
|
||||||
|
|
||||||
class TestDocumentBase:
|
class DocumentTestBase:
|
||||||
caption = "DocumentTest - *Caption*"
|
caption = "DocumentTest - *Caption*"
|
||||||
document_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.gif"
|
document_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.gif"
|
||||||
file_size = 12948
|
file_size = 12948
|
||||||
|
@ -62,7 +62,7 @@ class TestDocumentBase:
|
||||||
document_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
document_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
|
|
||||||
|
|
||||||
class TestDocumentWithoutRequest(TestDocumentBase):
|
class TestDocumentWithoutRequest(DocumentTestBase):
|
||||||
def test_slot_behaviour(self, document):
|
def test_slot_behaviour(self, document):
|
||||||
for attr in document.__slots__:
|
for attr in document.__slots__:
|
||||||
assert getattr(document, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(document, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -218,7 +218,7 @@ class TestDocumentWithoutRequest(TestDocumentBase):
|
||||||
assert await document.get_file()
|
assert await document.get_file()
|
||||||
|
|
||||||
|
|
||||||
class TestDocumentWithRequest(TestDocumentBase):
|
class TestDocumentWithRequest(DocumentTestBase):
|
||||||
async def test_error_send_empty_file(self, bot, chat_id):
|
async def test_error_send_empty_file(self, bot, chat_id):
|
||||||
with Path(os.devnull).open("rb") as f, pytest.raises(TelegramError):
|
with Path(os.devnull).open("rb") as f, pytest.raises(TelegramError):
|
||||||
await bot.send_document(chat_id=chat_id, document=f)
|
await bot.send_document(chat_id=chat_id, document=f)
|
||||||
|
|
|
@ -31,10 +31,10 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def file(bot):
|
def file(bot):
|
||||||
file = File(
|
file = File(
|
||||||
TestFileBase.file_id,
|
FileTestBase.file_id,
|
||||||
TestFileBase.file_unique_id,
|
FileTestBase.file_unique_id,
|
||||||
file_path=TestFileBase.file_path,
|
file_path=FileTestBase.file_path,
|
||||||
file_size=TestFileBase.file_size,
|
file_size=FileTestBase.file_size,
|
||||||
)
|
)
|
||||||
file.set_bot(bot)
|
file.set_bot(bot)
|
||||||
file._unfreeze()
|
file._unfreeze()
|
||||||
|
@ -51,10 +51,10 @@ def encrypted_file(bot):
|
||||||
"Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
|
"Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
|
||||||
)
|
)
|
||||||
ef = File(
|
ef = File(
|
||||||
TestFileBase.file_id,
|
FileTestBase.file_id,
|
||||||
TestFileBase.file_unique_id,
|
FileTestBase.file_unique_id,
|
||||||
TestFileBase.file_size,
|
FileTestBase.file_size,
|
||||||
TestFileBase.file_path,
|
FileTestBase.file_path,
|
||||||
)
|
)
|
||||||
ef.set_bot(bot)
|
ef.set_bot(bot)
|
||||||
ef.set_credentials(fc)
|
ef.set_credentials(fc)
|
||||||
|
@ -69,9 +69,9 @@ def encrypted_local_file(bot):
|
||||||
"Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
|
"Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
|
||||||
)
|
)
|
||||||
ef = File(
|
ef = File(
|
||||||
TestFileBase.file_id,
|
FileTestBase.file_id,
|
||||||
TestFileBase.file_unique_id,
|
FileTestBase.file_unique_id,
|
||||||
TestFileBase.file_size,
|
FileTestBase.file_size,
|
||||||
file_path=str(data_file("image_encrypted.jpg")),
|
file_path=str(data_file("image_encrypted.jpg")),
|
||||||
)
|
)
|
||||||
ef.set_bot(bot)
|
ef.set_bot(bot)
|
||||||
|
@ -82,16 +82,16 @@ def encrypted_local_file(bot):
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def local_file(bot):
|
def local_file(bot):
|
||||||
file = File(
|
file = File(
|
||||||
TestFileBase.file_id,
|
FileTestBase.file_id,
|
||||||
TestFileBase.file_unique_id,
|
FileTestBase.file_unique_id,
|
||||||
file_path=str(data_file("local_file.txt")),
|
file_path=str(data_file("local_file.txt")),
|
||||||
file_size=TestFileBase.file_size,
|
file_size=FileTestBase.file_size,
|
||||||
)
|
)
|
||||||
file.set_bot(bot)
|
file.set_bot(bot)
|
||||||
return file
|
return file
|
||||||
|
|
||||||
|
|
||||||
class TestFileBase:
|
class FileTestBase:
|
||||||
file_id = "NOTVALIDDOESNOTMATTER"
|
file_id = "NOTVALIDDOESNOTMATTER"
|
||||||
file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
file_path = (
|
file_path = (
|
||||||
|
@ -101,7 +101,7 @@ class TestFileBase:
|
||||||
file_content = "Saint-Saëns".encode() # Intentionally contains unicode chars.
|
file_content = "Saint-Saëns".encode() # Intentionally contains unicode chars.
|
||||||
|
|
||||||
|
|
||||||
class TestFileWithoutRequest(TestFileBase):
|
class TestFileWithoutRequest(FileTestBase):
|
||||||
def test_slot_behaviour(self, file):
|
def test_slot_behaviour(self, file):
|
||||||
for attr in file.__slots__:
|
for attr in file.__slots__:
|
||||||
assert getattr(file, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(file, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -273,7 +273,7 @@ class TestFileWithoutRequest(TestFileBase):
|
||||||
assert buf2[: len(buf)] == buf
|
assert buf2[: len(buf)] == buf
|
||||||
|
|
||||||
|
|
||||||
class TestFileWithRequest(TestFileBase):
|
class TestFileWithRequest(FileTestBase):
|
||||||
async def test_error_get_empty_file_id(self, bot):
|
async def test_error_get_empty_file_id(self, bot):
|
||||||
with pytest.raises(TelegramError):
|
with pytest.raises(TelegramError):
|
||||||
await bot.get_file(file_id="")
|
await bot.get_file(file_id="")
|
||||||
|
|
|
@ -68,94 +68,94 @@ from .test_video import video, video_file # noqa: F401
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_media_video(class_thumb_file):
|
def input_media_video(class_thumb_file):
|
||||||
return InputMediaVideo(
|
return InputMediaVideo(
|
||||||
media=TestInputMediaVideoBase.media,
|
media=InputMediaVideoTestBase.media,
|
||||||
caption=TestInputMediaVideoBase.caption,
|
caption=InputMediaVideoTestBase.caption,
|
||||||
width=TestInputMediaVideoBase.width,
|
width=InputMediaVideoTestBase.width,
|
||||||
height=TestInputMediaVideoBase.height,
|
height=InputMediaVideoTestBase.height,
|
||||||
duration=TestInputMediaVideoBase.duration,
|
duration=InputMediaVideoTestBase.duration,
|
||||||
parse_mode=TestInputMediaVideoBase.parse_mode,
|
parse_mode=InputMediaVideoTestBase.parse_mode,
|
||||||
caption_entities=TestInputMediaVideoBase.caption_entities,
|
caption_entities=InputMediaVideoTestBase.caption_entities,
|
||||||
thumbnail=class_thumb_file,
|
thumbnail=class_thumb_file,
|
||||||
supports_streaming=TestInputMediaVideoBase.supports_streaming,
|
supports_streaming=InputMediaVideoTestBase.supports_streaming,
|
||||||
has_spoiler=TestInputMediaVideoBase.has_spoiler,
|
has_spoiler=InputMediaVideoTestBase.has_spoiler,
|
||||||
show_caption_above_media=TestInputMediaVideoBase.show_caption_above_media,
|
show_caption_above_media=InputMediaVideoTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_media_photo():
|
def input_media_photo():
|
||||||
return InputMediaPhoto(
|
return InputMediaPhoto(
|
||||||
media=TestInputMediaPhotoBase.media,
|
media=InputMediaPhotoTestBase.media,
|
||||||
caption=TestInputMediaPhotoBase.caption,
|
caption=InputMediaPhotoTestBase.caption,
|
||||||
parse_mode=TestInputMediaPhotoBase.parse_mode,
|
parse_mode=InputMediaPhotoTestBase.parse_mode,
|
||||||
caption_entities=TestInputMediaPhotoBase.caption_entities,
|
caption_entities=InputMediaPhotoTestBase.caption_entities,
|
||||||
has_spoiler=TestInputMediaPhotoBase.has_spoiler,
|
has_spoiler=InputMediaPhotoTestBase.has_spoiler,
|
||||||
show_caption_above_media=TestInputMediaPhotoBase.show_caption_above_media,
|
show_caption_above_media=InputMediaPhotoTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_media_animation(class_thumb_file):
|
def input_media_animation(class_thumb_file):
|
||||||
return InputMediaAnimation(
|
return InputMediaAnimation(
|
||||||
media=TestInputMediaAnimationBase.media,
|
media=InputMediaAnimationTestBase.media,
|
||||||
caption=TestInputMediaAnimationBase.caption,
|
caption=InputMediaAnimationTestBase.caption,
|
||||||
parse_mode=TestInputMediaAnimationBase.parse_mode,
|
parse_mode=InputMediaAnimationTestBase.parse_mode,
|
||||||
caption_entities=TestInputMediaAnimationBase.caption_entities,
|
caption_entities=InputMediaAnimationTestBase.caption_entities,
|
||||||
width=TestInputMediaAnimationBase.width,
|
width=InputMediaAnimationTestBase.width,
|
||||||
height=TestInputMediaAnimationBase.height,
|
height=InputMediaAnimationTestBase.height,
|
||||||
thumbnail=class_thumb_file,
|
thumbnail=class_thumb_file,
|
||||||
duration=TestInputMediaAnimationBase.duration,
|
duration=InputMediaAnimationTestBase.duration,
|
||||||
has_spoiler=TestInputMediaAnimationBase.has_spoiler,
|
has_spoiler=InputMediaAnimationTestBase.has_spoiler,
|
||||||
show_caption_above_media=TestInputMediaAnimationBase.show_caption_above_media,
|
show_caption_above_media=InputMediaAnimationTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_media_audio(class_thumb_file):
|
def input_media_audio(class_thumb_file):
|
||||||
return InputMediaAudio(
|
return InputMediaAudio(
|
||||||
media=TestInputMediaAudioBase.media,
|
media=InputMediaAudioTestBase.media,
|
||||||
caption=TestInputMediaAudioBase.caption,
|
caption=InputMediaAudioTestBase.caption,
|
||||||
duration=TestInputMediaAudioBase.duration,
|
duration=InputMediaAudioTestBase.duration,
|
||||||
performer=TestInputMediaAudioBase.performer,
|
performer=InputMediaAudioTestBase.performer,
|
||||||
title=TestInputMediaAudioBase.title,
|
title=InputMediaAudioTestBase.title,
|
||||||
thumbnail=class_thumb_file,
|
thumbnail=class_thumb_file,
|
||||||
parse_mode=TestInputMediaAudioBase.parse_mode,
|
parse_mode=InputMediaAudioTestBase.parse_mode,
|
||||||
caption_entities=TestInputMediaAudioBase.caption_entities,
|
caption_entities=InputMediaAudioTestBase.caption_entities,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_media_document(class_thumb_file):
|
def input_media_document(class_thumb_file):
|
||||||
return InputMediaDocument(
|
return InputMediaDocument(
|
||||||
media=TestInputMediaDocumentBase.media,
|
media=InputMediaDocumentTestBase.media,
|
||||||
caption=TestInputMediaDocumentBase.caption,
|
caption=InputMediaDocumentTestBase.caption,
|
||||||
thumbnail=class_thumb_file,
|
thumbnail=class_thumb_file,
|
||||||
parse_mode=TestInputMediaDocumentBase.parse_mode,
|
parse_mode=InputMediaDocumentTestBase.parse_mode,
|
||||||
caption_entities=TestInputMediaDocumentBase.caption_entities,
|
caption_entities=InputMediaDocumentTestBase.caption_entities,
|
||||||
disable_content_type_detection=TestInputMediaDocumentBase.disable_content_type_detection,
|
disable_content_type_detection=InputMediaDocumentTestBase.disable_content_type_detection,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_paid_media_photo():
|
def input_paid_media_photo():
|
||||||
return InputPaidMediaPhoto(
|
return InputPaidMediaPhoto(
|
||||||
media=TestInputMediaPhotoBase.media,
|
media=InputMediaPhotoTestBase.media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_paid_media_video(class_thumb_file):
|
def input_paid_media_video(class_thumb_file):
|
||||||
return InputPaidMediaVideo(
|
return InputPaidMediaVideo(
|
||||||
media=TestInputMediaVideoBase.media,
|
media=InputMediaVideoTestBase.media,
|
||||||
thumbnail=class_thumb_file,
|
thumbnail=class_thumb_file,
|
||||||
width=TestInputMediaVideoBase.width,
|
width=InputMediaVideoTestBase.width,
|
||||||
height=TestInputMediaVideoBase.height,
|
height=InputMediaVideoTestBase.height,
|
||||||
duration=TestInputMediaVideoBase.duration,
|
duration=InputMediaVideoTestBase.duration,
|
||||||
supports_streaming=TestInputMediaVideoBase.supports_streaming,
|
supports_streaming=InputMediaVideoTestBase.supports_streaming,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaVideoBase:
|
class InputMediaVideoTestBase:
|
||||||
type_ = "video"
|
type_ = "video"
|
||||||
media = "NOTAREALFILEID"
|
media = "NOTAREALFILEID"
|
||||||
caption = "My Caption"
|
caption = "My Caption"
|
||||||
|
@ -169,7 +169,7 @@ class TestInputMediaVideoBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaVideoWithoutRequest(TestInputMediaVideoBase):
|
class TestInputMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||||
def test_slot_behaviour(self, input_media_video):
|
def test_slot_behaviour(self, input_media_video):
|
||||||
inst = input_media_video
|
inst = input_media_video
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -258,7 +258,7 @@ class TestInputMediaVideoWithoutRequest(TestInputMediaVideoBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaPhotoBase:
|
class InputMediaPhotoTestBase:
|
||||||
type_ = "photo"
|
type_ = "photo"
|
||||||
media = "NOTAREALFILEID"
|
media = "NOTAREALFILEID"
|
||||||
caption = "My Caption"
|
caption = "My Caption"
|
||||||
|
@ -268,7 +268,7 @@ class TestInputMediaPhotoBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
class TestInputMediaPhotoWithoutRequest(InputMediaPhotoTestBase):
|
||||||
def test_slot_behaviour(self, input_media_photo):
|
def test_slot_behaviour(self, input_media_photo):
|
||||||
inst = input_media_photo
|
inst = input_media_photo
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -322,7 +322,7 @@ class TestInputMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
||||||
assert input_media_photo.media == data_file("telegram.mp4").as_uri()
|
assert input_media_photo.media == data_file("telegram.mp4").as_uri()
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaAnimationBase:
|
class InputMediaAnimationTestBase:
|
||||||
type_ = "animation"
|
type_ = "animation"
|
||||||
media = "NOTAREALFILEID"
|
media = "NOTAREALFILEID"
|
||||||
caption = "My Caption"
|
caption = "My Caption"
|
||||||
|
@ -335,7 +335,7 @@ class TestInputMediaAnimationBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaAnimationWithoutRequest(TestInputMediaAnimationBase):
|
class TestInputMediaAnimationWithoutRequest(InputMediaAnimationTestBase):
|
||||||
def test_slot_behaviour(self, input_media_animation):
|
def test_slot_behaviour(self, input_media_animation):
|
||||||
inst = input_media_animation
|
inst = input_media_animation
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -396,7 +396,7 @@ class TestInputMediaAnimationWithoutRequest(TestInputMediaAnimationBase):
|
||||||
assert input_media_animation.thumbnail == data_file("telegram.jpg").as_uri()
|
assert input_media_animation.thumbnail == data_file("telegram.jpg").as_uri()
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaAudioBase:
|
class InputMediaAudioTestBase:
|
||||||
type_ = "audio"
|
type_ = "audio"
|
||||||
media = "NOTAREALFILEID"
|
media = "NOTAREALFILEID"
|
||||||
caption = "My Caption"
|
caption = "My Caption"
|
||||||
|
@ -407,7 +407,7 @@ class TestInputMediaAudioBase:
|
||||||
caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
|
caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaAudioWithoutRequest(TestInputMediaAudioBase):
|
class TestInputMediaAudioWithoutRequest(InputMediaAudioTestBase):
|
||||||
def test_slot_behaviour(self, input_media_audio):
|
def test_slot_behaviour(self, input_media_audio):
|
||||||
inst = input_media_audio
|
inst = input_media_audio
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -467,7 +467,7 @@ class TestInputMediaAudioWithoutRequest(TestInputMediaAudioBase):
|
||||||
assert input_media_audio.thumbnail == data_file("telegram.jpg").as_uri()
|
assert input_media_audio.thumbnail == data_file("telegram.jpg").as_uri()
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaDocumentBase:
|
class InputMediaDocumentTestBase:
|
||||||
type_ = "document"
|
type_ = "document"
|
||||||
media = "NOTAREALFILEID"
|
media = "NOTAREALFILEID"
|
||||||
caption = "My Caption"
|
caption = "My Caption"
|
||||||
|
@ -476,7 +476,7 @@ class TestInputMediaDocumentBase:
|
||||||
disable_content_type_detection = True
|
disable_content_type_detection = True
|
||||||
|
|
||||||
|
|
||||||
class TestInputMediaDocumentWithoutRequest(TestInputMediaDocumentBase):
|
class TestInputMediaDocumentWithoutRequest(InputMediaDocumentTestBase):
|
||||||
def test_slot_behaviour(self, input_media_document):
|
def test_slot_behaviour(self, input_media_document):
|
||||||
inst = input_media_document
|
inst = input_media_document
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -535,7 +535,7 @@ class TestInputMediaDocumentWithoutRequest(TestInputMediaDocumentBase):
|
||||||
assert input_media_document.thumbnail == data_file("telegram.jpg").as_uri()
|
assert input_media_document.thumbnail == data_file("telegram.jpg").as_uri()
|
||||||
|
|
||||||
|
|
||||||
class TestInputPaidMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
class TestInputPaidMediaPhotoWithoutRequest(InputMediaPhotoTestBase):
|
||||||
def test_slot_behaviour(self, input_paid_media_photo):
|
def test_slot_behaviour(self, input_paid_media_photo):
|
||||||
inst = input_paid_media_photo
|
inst = input_paid_media_photo
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -568,7 +568,7 @@ class TestInputPaidMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
||||||
assert input_paid_media_photo.media == data_file("telegram.jpg").as_uri()
|
assert input_paid_media_photo.media == data_file("telegram.jpg").as_uri()
|
||||||
|
|
||||||
|
|
||||||
class TestInputPaidMediaVideoWithoutRequest(TestInputMediaVideoBase):
|
class TestInputPaidMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||||
def test_slot_behaviour(self, input_paid_media_video):
|
def test_slot_behaviour(self, input_paid_media_video):
|
||||||
inst = input_paid_media_video
|
inst = input_paid_media_video
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -29,15 +29,15 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_sticker():
|
def input_sticker():
|
||||||
return InputSticker(
|
return InputSticker(
|
||||||
sticker=TestInputStickerBase.sticker,
|
sticker=InputStickerTestBase.sticker,
|
||||||
emoji_list=TestInputStickerBase.emoji_list,
|
emoji_list=InputStickerTestBase.emoji_list,
|
||||||
mask_position=TestInputStickerBase.mask_position,
|
mask_position=InputStickerTestBase.mask_position,
|
||||||
keywords=TestInputStickerBase.keywords,
|
keywords=InputStickerTestBase.keywords,
|
||||||
format=TestInputStickerBase.format,
|
format=InputStickerTestBase.format,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputStickerBase:
|
class InputStickerTestBase:
|
||||||
sticker = "fake_file_id"
|
sticker = "fake_file_id"
|
||||||
emoji_list = ("👍", "👎")
|
emoji_list = ("👍", "👎")
|
||||||
mask_position = MaskPosition("forehead", 0.5, 0.5, 0.5)
|
mask_position = MaskPosition("forehead", 0.5, 0.5, 0.5)
|
||||||
|
@ -45,7 +45,7 @@ class TestInputStickerBase:
|
||||||
format = "static"
|
format = "static"
|
||||||
|
|
||||||
|
|
||||||
class TestInputStickerWithoutRequest(TestInputStickerBase):
|
class TestInputStickerWithoutRequest(InputStickerTestBase):
|
||||||
def test_slot_behaviour(self, input_sticker):
|
def test_slot_behaviour(self, input_sticker):
|
||||||
inst = input_sticker
|
inst = input_sticker
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -31,16 +31,16 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def location():
|
def location():
|
||||||
return Location(
|
return Location(
|
||||||
latitude=TestLocationBase.latitude,
|
latitude=LocationTestBase.latitude,
|
||||||
longitude=TestLocationBase.longitude,
|
longitude=LocationTestBase.longitude,
|
||||||
horizontal_accuracy=TestLocationBase.horizontal_accuracy,
|
horizontal_accuracy=LocationTestBase.horizontal_accuracy,
|
||||||
live_period=TestLocationBase.live_period,
|
live_period=LocationTestBase.live_period,
|
||||||
heading=TestLocationBase.live_period,
|
heading=LocationTestBase.live_period,
|
||||||
proximity_alert_radius=TestLocationBase.proximity_alert_radius,
|
proximity_alert_radius=LocationTestBase.proximity_alert_radius,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestLocationBase:
|
class LocationTestBase:
|
||||||
latitude = -23.691288
|
latitude = -23.691288
|
||||||
longitude = -46.788279
|
longitude = -46.788279
|
||||||
horizontal_accuracy = 999
|
horizontal_accuracy = 999
|
||||||
|
@ -49,7 +49,7 @@ class TestLocationBase:
|
||||||
proximity_alert_radius = 50
|
proximity_alert_radius = 50
|
||||||
|
|
||||||
|
|
||||||
class TestLocationWithoutRequest(TestLocationBase):
|
class TestLocationWithoutRequest(LocationTestBase):
|
||||||
def test_slot_behaviour(self, location):
|
def test_slot_behaviour(self, location):
|
||||||
for attr in location.__slots__:
|
for attr in location.__slots__:
|
||||||
assert getattr(location, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(location, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
|
|
@ -65,7 +65,7 @@ def photo(photolist):
|
||||||
return photolist[-1]
|
return photolist[-1]
|
||||||
|
|
||||||
|
|
||||||
class TestPhotoBase:
|
class PhotoTestBase:
|
||||||
width = 800
|
width = 800
|
||||||
height = 800
|
height = 800
|
||||||
caption = "<b>PhotoTest</b> - *Caption*"
|
caption = "<b>PhotoTest</b> - *Caption*"
|
||||||
|
@ -75,7 +75,7 @@ class TestPhotoBase:
|
||||||
file_size = [29176, 27662]
|
file_size = [29176, 27662]
|
||||||
|
|
||||||
|
|
||||||
class TestPhotoWithoutRequest(TestPhotoBase):
|
class TestPhotoWithoutRequest(PhotoTestBase):
|
||||||
def test_slot_behaviour(self, photo):
|
def test_slot_behaviour(self, photo):
|
||||||
for attr in photo.__slots__:
|
for attr in photo.__slots__:
|
||||||
assert getattr(photo, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(photo, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -237,7 +237,7 @@ class TestPhotoWithoutRequest(TestPhotoBase):
|
||||||
await default_bot.send_photo(chat_id, photo, reply_parameters=ReplyParameters(**kwargs))
|
await default_bot.send_photo(chat_id, photo, reply_parameters=ReplyParameters(**kwargs))
|
||||||
|
|
||||||
|
|
||||||
class TestPhotoWithRequest(TestPhotoBase):
|
class TestPhotoWithRequest(PhotoTestBase):
|
||||||
async def test_send_photo_all_args(self, bot, chat_id, photo_file):
|
async def test_send_photo_all_args(self, bot, chat_id, photo_file):
|
||||||
message = await bot.send_photo(
|
message = await bot.send_photo(
|
||||||
chat_id,
|
chat_id,
|
||||||
|
|
|
@ -61,7 +61,7 @@ async def sticker(bot, chat_id):
|
||||||
sticker = (await bot.send_sticker(chat_id, sticker=f, read_timeout=50)).sticker
|
sticker = (await bot.send_sticker(chat_id, sticker=f, read_timeout=50)).sticker
|
||||||
# necessary to properly test needs_repainting
|
# necessary to properly test needs_repainting
|
||||||
with sticker._unfrozen():
|
with sticker._unfrozen():
|
||||||
sticker.needs_repainting = TestStickerBase.needs_repainting
|
sticker.needs_repainting = StickerTestBase.needs_repainting
|
||||||
return sticker
|
return sticker
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ def video_sticker(bot, chat_id):
|
||||||
return bot.send_sticker(chat_id, sticker=f, timeout=50).sticker
|
return bot.send_sticker(chat_id, sticker=f, timeout=50).sticker
|
||||||
|
|
||||||
|
|
||||||
class TestStickerBase:
|
class StickerTestBase:
|
||||||
# sticker_file_url = 'https://python-telegram-bot.org/static/testfiles/telegram.webp'
|
# sticker_file_url = 'https://python-telegram-bot.org/static/testfiles/telegram.webp'
|
||||||
# Serving sticker from gh since our server sends wrong content_type
|
# Serving sticker from gh since our server sends wrong content_type
|
||||||
sticker_file_url = (
|
sticker_file_url = (
|
||||||
|
@ -116,7 +116,7 @@ class TestStickerBase:
|
||||||
premium_animation = File("this_is_an_id", "this_is_an_unique_id")
|
premium_animation = File("this_is_an_id", "this_is_an_unique_id")
|
||||||
|
|
||||||
|
|
||||||
class TestStickerWithoutRequest(TestStickerBase):
|
class TestStickerWithoutRequest(StickerTestBase):
|
||||||
def test_slot_behaviour(self, sticker):
|
def test_slot_behaviour(self, sticker):
|
||||||
for attr in sticker.__slots__:
|
for attr in sticker.__slots__:
|
||||||
assert getattr(sticker, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(sticker, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -345,7 +345,7 @@ class TestStickerWithoutRequest(TestStickerBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestStickerWithRequest(TestStickerBase):
|
class TestStickerWithRequest(StickerTestBase):
|
||||||
async def test_send_all_args(self, bot, chat_id, sticker_file, sticker):
|
async def test_send_all_args(self, bot, chat_id, sticker_file, sticker):
|
||||||
message = await bot.send_sticker(
|
message = await bot.send_sticker(
|
||||||
chat_id, sticker=sticker_file, disable_notification=False, protect_content=True
|
chat_id, sticker=sticker_file, disable_notification=False, protect_content=True
|
||||||
|
@ -572,7 +572,7 @@ def sticker_set_thumb_file():
|
||||||
yield file
|
yield file
|
||||||
|
|
||||||
|
|
||||||
class TestStickerSetBase:
|
class StickerSetTestBase:
|
||||||
title = "Test stickers"
|
title = "Test stickers"
|
||||||
stickers = [Sticker("file_id", "file_un_id", 512, 512, True, True, Sticker.REGULAR)]
|
stickers = [Sticker("file_id", "file_un_id", 512, 512, True, True, Sticker.REGULAR)]
|
||||||
name = "NOTAREALNAME"
|
name = "NOTAREALNAME"
|
||||||
|
@ -580,7 +580,7 @@ class TestStickerSetBase:
|
||||||
contains_masks = True
|
contains_masks = True
|
||||||
|
|
||||||
|
|
||||||
class TestStickerSetWithoutRequest(TestStickerSetBase):
|
class TestStickerSetWithoutRequest(StickerSetTestBase):
|
||||||
def test_slot_behaviour(self):
|
def test_slot_behaviour(self):
|
||||||
inst = StickerSet("this", "is", self.stickers, "not")
|
inst = StickerSet("this", "is", self.stickers, "not")
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -1064,21 +1064,21 @@ class TestStickerSetWithRequest:
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def mask_position():
|
def mask_position():
|
||||||
return MaskPosition(
|
return MaskPosition(
|
||||||
TestMaskPositionBase.point,
|
MaskPositionTestBase.point,
|
||||||
TestMaskPositionBase.x_shift,
|
MaskPositionTestBase.x_shift,
|
||||||
TestMaskPositionBase.y_shift,
|
MaskPositionTestBase.y_shift,
|
||||||
TestMaskPositionBase.scale,
|
MaskPositionTestBase.scale,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestMaskPositionBase:
|
class MaskPositionTestBase:
|
||||||
point = MaskPosition.EYES
|
point = MaskPosition.EYES
|
||||||
x_shift = -1
|
x_shift = -1
|
||||||
y_shift = 1
|
y_shift = 1
|
||||||
scale = 2
|
scale = 2
|
||||||
|
|
||||||
|
|
||||||
class TestMaskPositionWithoutRequest(TestMaskPositionBase):
|
class TestMaskPositionWithoutRequest(MaskPositionTestBase):
|
||||||
def test_slot_behaviour(self, mask_position):
|
def test_slot_behaviour(self, mask_position):
|
||||||
inst = mask_position
|
inst = mask_position
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -1130,7 +1130,7 @@ class TestMaskPositionWithoutRequest(TestMaskPositionBase):
|
||||||
assert hash(a) != hash(e)
|
assert hash(a) != hash(e)
|
||||||
|
|
||||||
|
|
||||||
class TestMaskPositionWithRequest(TestMaskPositionBase):
|
class TestMaskPositionWithRequest(MaskPositionTestBase):
|
||||||
async def test_create_new_mask_sticker_set(self, bot, chat_id, sticker_file, mask_position):
|
async def test_create_new_mask_sticker_set(self, bot, chat_id, sticker_file, mask_position):
|
||||||
name = f"masks_by_{bot.username}"
|
name = f"masks_by_{bot.username}"
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -31,17 +31,17 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def venue():
|
def venue():
|
||||||
return Venue(
|
return Venue(
|
||||||
TestVenueBase.location,
|
VenueTestBase.location,
|
||||||
TestVenueBase.title,
|
VenueTestBase.title,
|
||||||
TestVenueBase.address,
|
VenueTestBase.address,
|
||||||
foursquare_id=TestVenueBase.foursquare_id,
|
foursquare_id=VenueTestBase.foursquare_id,
|
||||||
foursquare_type=TestVenueBase.foursquare_type,
|
foursquare_type=VenueTestBase.foursquare_type,
|
||||||
google_place_id=TestVenueBase.google_place_id,
|
google_place_id=VenueTestBase.google_place_id,
|
||||||
google_place_type=TestVenueBase.google_place_type,
|
google_place_type=VenueTestBase.google_place_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestVenueBase:
|
class VenueTestBase:
|
||||||
location = Location(longitude=-46.788279, latitude=-23.691288)
|
location = Location(longitude=-46.788279, latitude=-23.691288)
|
||||||
title = "title"
|
title = "title"
|
||||||
address = "address"
|
address = "address"
|
||||||
|
@ -51,7 +51,7 @@ class TestVenueBase:
|
||||||
google_place_type = "google place type"
|
google_place_type = "google place type"
|
||||||
|
|
||||||
|
|
||||||
class TestVenueWithoutRequest(TestVenueBase):
|
class TestVenueWithoutRequest(VenueTestBase):
|
||||||
def test_slot_behaviour(self, venue):
|
def test_slot_behaviour(self, venue):
|
||||||
for attr in venue.__slots__:
|
for attr in venue.__slots__:
|
||||||
assert getattr(venue, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(venue, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -171,7 +171,7 @@ class TestVenueWithoutRequest(TestVenueBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestVenueWithRequest(TestVenueBase):
|
class TestVenueWithRequest(VenueTestBase):
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("default_bot", "custom"),
|
("default_bot", "custom"),
|
||||||
[
|
[
|
||||||
|
|
|
@ -49,7 +49,7 @@ async def video(bot, chat_id):
|
||||||
return (await bot.send_video(chat_id, video=f, read_timeout=50)).video
|
return (await bot.send_video(chat_id, video=f, read_timeout=50)).video
|
||||||
|
|
||||||
|
|
||||||
class TestVideoBase:
|
class VideoTestBase:
|
||||||
width = 360
|
width = 360
|
||||||
height = 640
|
height = 640
|
||||||
duration = 5
|
duration = 5
|
||||||
|
@ -66,7 +66,7 @@ class TestVideoBase:
|
||||||
video_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
video_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
|
|
||||||
|
|
||||||
class TestVideoWithoutRequest(TestVideoBase):
|
class TestVideoWithoutRequest(VideoTestBase):
|
||||||
def test_slot_behaviour(self, video):
|
def test_slot_behaviour(self, video):
|
||||||
for attr in video.__slots__:
|
for attr in video.__slots__:
|
||||||
assert getattr(video, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(video, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -229,7 +229,7 @@ class TestVideoWithoutRequest(TestVideoBase):
|
||||||
await default_bot.send_video(chat_id, video, reply_parameters=ReplyParameters(**kwargs))
|
await default_bot.send_video(chat_id, video, reply_parameters=ReplyParameters(**kwargs))
|
||||||
|
|
||||||
|
|
||||||
class TestVideoWithRequest(TestVideoBase):
|
class TestVideoWithRequest(VideoTestBase):
|
||||||
async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file):
|
async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file):
|
||||||
message = await bot.send_video(
|
message = await bot.send_video(
|
||||||
chat_id,
|
chat_id,
|
||||||
|
|
|
@ -48,7 +48,7 @@ async def video_note(bot, chat_id):
|
||||||
return (await bot.send_video_note(chat_id, video_note=f, read_timeout=50)).video_note
|
return (await bot.send_video_note(chat_id, video_note=f, read_timeout=50)).video_note
|
||||||
|
|
||||||
|
|
||||||
class TestVideoNoteBase:
|
class VideoNoteTestBase:
|
||||||
length = 240
|
length = 240
|
||||||
duration = 3
|
duration = 3
|
||||||
file_size = 132084
|
file_size = 132084
|
||||||
|
@ -60,7 +60,7 @@ class TestVideoNoteBase:
|
||||||
videonote_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
videonote_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
|
|
||||||
|
|
||||||
class TestVideoNoteWithoutRequest(TestVideoNoteBase):
|
class TestVideoNoteWithoutRequest(VideoNoteTestBase):
|
||||||
def test_slot_behaviour(self, video_note):
|
def test_slot_behaviour(self, video_note):
|
||||||
for attr in video_note.__slots__:
|
for attr in video_note.__slots__:
|
||||||
assert getattr(video_note, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(video_note, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -218,7 +218,7 @@ class TestVideoNoteWithoutRequest(TestVideoNoteBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestVideoNoteWithRequest(TestVideoNoteBase):
|
class TestVideoNoteWithRequest(VideoNoteTestBase):
|
||||||
async def test_send_all_args(self, bot, chat_id, video_note_file, video_note, thumb_file):
|
async def test_send_all_args(self, bot, chat_id, video_note_file, video_note, thumb_file):
|
||||||
message = await bot.send_video_note(
|
message = await bot.send_video_note(
|
||||||
chat_id,
|
chat_id,
|
||||||
|
|
|
@ -49,7 +49,7 @@ async def voice(bot, chat_id):
|
||||||
return (await bot.send_voice(chat_id, voice=f, read_timeout=50)).voice
|
return (await bot.send_voice(chat_id, voice=f, read_timeout=50)).voice
|
||||||
|
|
||||||
|
|
||||||
class TestVoiceBase:
|
class VoiceTestBase:
|
||||||
duration = 3
|
duration = 3
|
||||||
mime_type = "audio/ogg"
|
mime_type = "audio/ogg"
|
||||||
file_size = 9199
|
file_size = 9199
|
||||||
|
@ -59,7 +59,7 @@ class TestVoiceBase:
|
||||||
voice_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
voice_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||||
|
|
||||||
|
|
||||||
class TestVoiceWithoutRequest(TestVoiceBase):
|
class TestVoiceWithoutRequest(VoiceTestBase):
|
||||||
def test_slot_behaviour(self, voice):
|
def test_slot_behaviour(self, voice):
|
||||||
for attr in voice.__slots__:
|
for attr in voice.__slots__:
|
||||||
assert getattr(voice, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(voice, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
@ -203,7 +203,7 @@ class TestVoiceWithoutRequest(TestVoiceBase):
|
||||||
await default_bot.send_voice(chat_id, voice, reply_parameters=ReplyParameters(**kwargs))
|
await default_bot.send_voice(chat_id, voice, reply_parameters=ReplyParameters(**kwargs))
|
||||||
|
|
||||||
|
|
||||||
class TestVoiceWithRequest(TestVoiceBase):
|
class TestVoiceWithRequest(VoiceTestBase):
|
||||||
async def test_send_all_args(self, bot, chat_id, voice_file, voice):
|
async def test_send_all_args(self, bot, chat_id, voice_file, voice):
|
||||||
message = await bot.send_voice(
|
message = await bot.send_voice(
|
||||||
chat_id,
|
chat_id,
|
||||||
|
|
|
@ -26,18 +26,18 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def game():
|
def game():
|
||||||
game = Game(
|
game = Game(
|
||||||
TestGameBase.title,
|
GameTestBase.title,
|
||||||
TestGameBase.description,
|
GameTestBase.description,
|
||||||
TestGameBase.photo,
|
GameTestBase.photo,
|
||||||
text=TestGameBase.text,
|
text=GameTestBase.text,
|
||||||
text_entities=TestGameBase.text_entities,
|
text_entities=GameTestBase.text_entities,
|
||||||
animation=TestGameBase.animation,
|
animation=GameTestBase.animation,
|
||||||
)
|
)
|
||||||
game._unfreeze()
|
game._unfreeze()
|
||||||
return game
|
return game
|
||||||
|
|
||||||
|
|
||||||
class TestGameBase:
|
class GameTestBase:
|
||||||
title = "Python-telegram-bot Test Game"
|
title = "Python-telegram-bot Test Game"
|
||||||
description = "description"
|
description = "description"
|
||||||
photo = [PhotoSize("Blah", "ElseBlah", 640, 360, file_size=0)]
|
photo = [PhotoSize("Blah", "ElseBlah", 640, 360, file_size=0)]
|
||||||
|
@ -49,7 +49,7 @@ class TestGameBase:
|
||||||
animation = Animation("blah", "unique_id", 320, 180, 1)
|
animation = Animation("blah", "unique_id", 320, 180, 1)
|
||||||
|
|
||||||
|
|
||||||
class TestGameWithoutRequest(TestGameBase):
|
class TestGameWithoutRequest(GameTestBase):
|
||||||
def test_slot_behaviour(self, game):
|
def test_slot_behaviour(self, game):
|
||||||
for attr in game.__slots__:
|
for attr in game.__slots__:
|
||||||
assert getattr(game, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(game, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
|
|
@ -26,17 +26,17 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def game_highscore():
|
def game_highscore():
|
||||||
return GameHighScore(
|
return GameHighScore(
|
||||||
TestGameHighScoreBase.position, TestGameHighScoreBase.user, TestGameHighScoreBase.score
|
GameHighScoreTestBase.position, GameHighScoreTestBase.user, GameHighScoreTestBase.score
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestGameHighScoreBase:
|
class GameHighScoreTestBase:
|
||||||
position = 12
|
position = 12
|
||||||
user = User(2, "test user", False)
|
user = User(2, "test user", False)
|
||||||
score = 42
|
score = 42
|
||||||
|
|
||||||
|
|
||||||
class TestGameHighScoreWithoutRequest(TestGameHighScoreBase):
|
class TestGameHighScoreWithoutRequest(GameHighScoreTestBase):
|
||||||
def test_slot_behaviour(self, game_highscore):
|
def test_slot_behaviour(self, game_highscore):
|
||||||
for attr in game_highscore.__slots__:
|
for attr in game_highscore.__slots__:
|
||||||
assert getattr(game_highscore, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(game_highscore, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
|
|
@ -32,24 +32,24 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_keyboard_button():
|
def inline_keyboard_button():
|
||||||
return InlineKeyboardButton(
|
return InlineKeyboardButton(
|
||||||
TestInlineKeyboardButtonBase.text,
|
InlineKeyboardButtonTestBase.text,
|
||||||
url=TestInlineKeyboardButtonBase.url,
|
url=InlineKeyboardButtonTestBase.url,
|
||||||
callback_data=TestInlineKeyboardButtonBase.callback_data,
|
callback_data=InlineKeyboardButtonTestBase.callback_data,
|
||||||
switch_inline_query=TestInlineKeyboardButtonBase.switch_inline_query,
|
switch_inline_query=InlineKeyboardButtonTestBase.switch_inline_query,
|
||||||
switch_inline_query_current_chat=(
|
switch_inline_query_current_chat=(
|
||||||
TestInlineKeyboardButtonBase.switch_inline_query_current_chat
|
InlineKeyboardButtonTestBase.switch_inline_query_current_chat
|
||||||
),
|
),
|
||||||
callback_game=TestInlineKeyboardButtonBase.callback_game,
|
callback_game=InlineKeyboardButtonTestBase.callback_game,
|
||||||
pay=TestInlineKeyboardButtonBase.pay,
|
pay=InlineKeyboardButtonTestBase.pay,
|
||||||
login_url=TestInlineKeyboardButtonBase.login_url,
|
login_url=InlineKeyboardButtonTestBase.login_url,
|
||||||
web_app=TestInlineKeyboardButtonBase.web_app,
|
web_app=InlineKeyboardButtonTestBase.web_app,
|
||||||
switch_inline_query_chosen_chat=(
|
switch_inline_query_chosen_chat=(
|
||||||
TestInlineKeyboardButtonBase.switch_inline_query_chosen_chat
|
InlineKeyboardButtonTestBase.switch_inline_query_chosen_chat
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineKeyboardButtonBase:
|
class InlineKeyboardButtonTestBase:
|
||||||
text = "text"
|
text = "text"
|
||||||
url = "url"
|
url = "url"
|
||||||
callback_data = "callback data"
|
callback_data = "callback data"
|
||||||
|
@ -62,7 +62,7 @@ class TestInlineKeyboardButtonBase:
|
||||||
switch_inline_query_chosen_chat = SwitchInlineQueryChosenChat("a_bot", True, False, True, True)
|
switch_inline_query_chosen_chat = SwitchInlineQueryChosenChat("a_bot", True, False, True, True)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineKeyboardButtonWithoutRequest(TestInlineKeyboardButtonBase):
|
class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase):
|
||||||
def test_slot_behaviour(self, inline_keyboard_button):
|
def test_slot_behaviour(self, inline_keyboard_button):
|
||||||
inst = inline_keyboard_button
|
inst = inline_keyboard_button
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -31,10 +31,10 @@ from tests.auxil.slots import mro_slots
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_keyboard_markup():
|
def inline_keyboard_markup():
|
||||||
return InlineKeyboardMarkup(TestInlineKeyboardMarkupBase.inline_keyboard)
|
return InlineKeyboardMarkup(InlineKeyboardMarkupTestBase.inline_keyboard)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineKeyboardMarkupBase:
|
class InlineKeyboardMarkupTestBase:
|
||||||
inline_keyboard = [
|
inline_keyboard = [
|
||||||
[
|
[
|
||||||
InlineKeyboardButton(text="button1", callback_data="data1"),
|
InlineKeyboardButton(text="button1", callback_data="data1"),
|
||||||
|
@ -43,7 +43,7 @@ class TestInlineKeyboardMarkupBase:
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestInlineKeyboardMarkupWithoutRequest(TestInlineKeyboardMarkupBase):
|
class TestInlineKeyboardMarkupWithoutRequest(InlineKeyboardMarkupTestBase):
|
||||||
def test_slot_behaviour(self, inline_keyboard_markup):
|
def test_slot_behaviour(self, inline_keyboard_markup):
|
||||||
inst = inline_keyboard_markup
|
inst = inline_keyboard_markup
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
@ -228,7 +228,7 @@ class TestInlineKeyboardMarkupWithoutRequest(TestInlineKeyboardMarkupBase):
|
||||||
await bot.send_message(123, "test", reply_markup=inline_keyboard_markup)
|
await bot.send_message(123, "test", reply_markup=inline_keyboard_markup)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineKeyborardMarkupWithRequest(TestInlineKeyboardMarkupBase):
|
class TestInlineKeyborardMarkupWithRequest(InlineKeyboardMarkupTestBase):
|
||||||
async def test_send_message_with_inline_keyboard_markup(
|
async def test_send_message_with_inline_keyboard_markup(
|
||||||
self, bot, chat_id, inline_keyboard_markup
|
self, bot, chat_id, inline_keyboard_markup
|
||||||
):
|
):
|
||||||
|
|
|
@ -31,17 +31,17 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query(bot):
|
def inline_query(bot):
|
||||||
ilq = InlineQuery(
|
ilq = InlineQuery(
|
||||||
TestInlineQueryBase.id_,
|
InlineQueryTestBase.id_,
|
||||||
TestInlineQueryBase.from_user,
|
InlineQueryTestBase.from_user,
|
||||||
TestInlineQueryBase.query,
|
InlineQueryTestBase.query,
|
||||||
TestInlineQueryBase.offset,
|
InlineQueryTestBase.offset,
|
||||||
location=TestInlineQueryBase.location,
|
location=InlineQueryTestBase.location,
|
||||||
)
|
)
|
||||||
ilq.set_bot(bot)
|
ilq.set_bot(bot)
|
||||||
return ilq
|
return ilq
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryBase:
|
class InlineQueryTestBase:
|
||||||
id_ = 1234
|
id_ = 1234
|
||||||
from_user = User(1, "First name", False)
|
from_user = User(1, "First name", False)
|
||||||
query = "query text"
|
query = "query text"
|
||||||
|
@ -49,7 +49,7 @@ class TestInlineQueryBase:
|
||||||
location = Location(8.8, 53.1)
|
location = Location(8.8, 53.1)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryWithoutRequest(TestInlineQueryBase):
|
class TestInlineQueryWithoutRequest(InlineQueryTestBase):
|
||||||
def test_slot_behaviour(self, inline_query):
|
def test_slot_behaviour(self, inline_query):
|
||||||
for attr in inline_query.__slots__:
|
for attr in inline_query.__slots__:
|
||||||
assert getattr(inline_query, attr, "err") != "err", f"got extra slot '{attr}'"
|
assert getattr(inline_query, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||||
|
|
|
@ -34,20 +34,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_article():
|
def inline_query_result_article():
|
||||||
return InlineQueryResultArticle(
|
return InlineQueryResultArticle(
|
||||||
TestInlineQueryResultArticleBase.id_,
|
InlineQueryResultArticleTestBase.id_,
|
||||||
TestInlineQueryResultArticleBase.title,
|
InlineQueryResultArticleTestBase.title,
|
||||||
input_message_content=TestInlineQueryResultArticleBase.input_message_content,
|
input_message_content=InlineQueryResultArticleTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultArticleBase.reply_markup,
|
reply_markup=InlineQueryResultArticleTestBase.reply_markup,
|
||||||
url=TestInlineQueryResultArticleBase.url,
|
url=InlineQueryResultArticleTestBase.url,
|
||||||
hide_url=TestInlineQueryResultArticleBase.hide_url,
|
hide_url=InlineQueryResultArticleTestBase.hide_url,
|
||||||
description=TestInlineQueryResultArticleBase.description,
|
description=InlineQueryResultArticleTestBase.description,
|
||||||
thumbnail_url=TestInlineQueryResultArticleBase.thumbnail_url,
|
thumbnail_url=InlineQueryResultArticleTestBase.thumbnail_url,
|
||||||
thumbnail_height=TestInlineQueryResultArticleBase.thumbnail_height,
|
thumbnail_height=InlineQueryResultArticleTestBase.thumbnail_height,
|
||||||
thumbnail_width=TestInlineQueryResultArticleBase.thumbnail_width,
|
thumbnail_width=InlineQueryResultArticleTestBase.thumbnail_width,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultArticleBase:
|
class InlineQueryResultArticleTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "article"
|
type_ = "article"
|
||||||
title = "title"
|
title = "title"
|
||||||
|
@ -61,7 +61,7 @@ class TestInlineQueryResultArticleBase:
|
||||||
thumbnail_width = 15
|
thumbnail_width = 15
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultArticleWithoutRequest(TestInlineQueryResultArticleBase):
|
class TestInlineQueryResultArticleWithoutRequest(InlineQueryResultArticleTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_article):
|
def test_slot_behaviour(self, inline_query_result_article):
|
||||||
inst = inline_query_result_article
|
inst = inline_query_result_article
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -33,20 +33,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_audio():
|
def inline_query_result_audio():
|
||||||
return InlineQueryResultAudio(
|
return InlineQueryResultAudio(
|
||||||
TestInlineQueryResultAudioBase.id_,
|
InlineQueryResultAudioTestBase.id_,
|
||||||
TestInlineQueryResultAudioBase.audio_url,
|
InlineQueryResultAudioTestBase.audio_url,
|
||||||
TestInlineQueryResultAudioBase.title,
|
InlineQueryResultAudioTestBase.title,
|
||||||
performer=TestInlineQueryResultAudioBase.performer,
|
performer=InlineQueryResultAudioTestBase.performer,
|
||||||
audio_duration=TestInlineQueryResultAudioBase.audio_duration,
|
audio_duration=InlineQueryResultAudioTestBase.audio_duration,
|
||||||
caption=TestInlineQueryResultAudioBase.caption,
|
caption=InlineQueryResultAudioTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultAudioBase.parse_mode,
|
parse_mode=InlineQueryResultAudioTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultAudioBase.caption_entities,
|
caption_entities=InlineQueryResultAudioTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultAudioBase.input_message_content,
|
input_message_content=InlineQueryResultAudioTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultAudioBase.reply_markup,
|
reply_markup=InlineQueryResultAudioTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultAudioBase:
|
class InlineQueryResultAudioTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "audio"
|
type_ = "audio"
|
||||||
audio_url = "audio url"
|
audio_url = "audio url"
|
||||||
|
@ -60,7 +60,7 @@ class TestInlineQueryResultAudioBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultAudioWithoutRequest(TestInlineQueryResultAudioBase):
|
class TestInlineQueryResultAudioWithoutRequest(InlineQueryResultAudioTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_audio):
|
def test_slot_behaviour(self, inline_query_result_audio):
|
||||||
inst = inline_query_result_audio
|
inst = inline_query_result_audio
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -33,17 +33,17 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_audio():
|
def inline_query_result_cached_audio():
|
||||||
return InlineQueryResultCachedAudio(
|
return InlineQueryResultCachedAudio(
|
||||||
TestInlineQueryResultCachedAudioBase.id_,
|
InlineQueryResultCachedAudioTestBase.id_,
|
||||||
TestInlineQueryResultCachedAudioBase.audio_file_id,
|
InlineQueryResultCachedAudioTestBase.audio_file_id,
|
||||||
caption=TestInlineQueryResultCachedAudioBase.caption,
|
caption=InlineQueryResultCachedAudioTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedAudioBase.parse_mode,
|
parse_mode=InlineQueryResultCachedAudioTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedAudioBase.caption_entities,
|
caption_entities=InlineQueryResultCachedAudioTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultCachedAudioBase.input_message_content,
|
input_message_content=InlineQueryResultCachedAudioTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedAudioBase.reply_markup,
|
reply_markup=InlineQueryResultCachedAudioTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedAudioBase:
|
class InlineQueryResultCachedAudioTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "audio"
|
type_ = "audio"
|
||||||
audio_file_id = "audio file id"
|
audio_file_id = "audio file id"
|
||||||
|
@ -54,7 +54,7 @@ class TestInlineQueryResultCachedAudioBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedAudioWithoutRequest(TestInlineQueryResultCachedAudioBase):
|
class TestInlineQueryResultCachedAudioWithoutRequest(InlineQueryResultCachedAudioTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_audio):
|
def test_slot_behaviour(self, inline_query_result_cached_audio):
|
||||||
inst = inline_query_result_cached_audio
|
inst = inline_query_result_cached_audio
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -33,19 +33,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_document():
|
def inline_query_result_cached_document():
|
||||||
return InlineQueryResultCachedDocument(
|
return InlineQueryResultCachedDocument(
|
||||||
TestInlineQueryResultCachedDocumentBase.id_,
|
InlineQueryResultCachedDocumentTestBase.id_,
|
||||||
TestInlineQueryResultCachedDocumentBase.title,
|
InlineQueryResultCachedDocumentTestBase.title,
|
||||||
TestInlineQueryResultCachedDocumentBase.document_file_id,
|
InlineQueryResultCachedDocumentTestBase.document_file_id,
|
||||||
caption=TestInlineQueryResultCachedDocumentBase.caption,
|
caption=InlineQueryResultCachedDocumentTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedDocumentBase.parse_mode,
|
parse_mode=InlineQueryResultCachedDocumentTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedDocumentBase.caption_entities,
|
caption_entities=InlineQueryResultCachedDocumentTestBase.caption_entities,
|
||||||
description=TestInlineQueryResultCachedDocumentBase.description,
|
description=InlineQueryResultCachedDocumentTestBase.description,
|
||||||
input_message_content=TestInlineQueryResultCachedDocumentBase.input_message_content,
|
input_message_content=InlineQueryResultCachedDocumentTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedDocumentBase.reply_markup,
|
reply_markup=InlineQueryResultCachedDocumentTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedDocumentBase:
|
class InlineQueryResultCachedDocumentTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "document"
|
type_ = "document"
|
||||||
document_file_id = "document file id"
|
document_file_id = "document file id"
|
||||||
|
@ -58,7 +58,7 @@ class TestInlineQueryResultCachedDocumentBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedDocumentWithoutRequest(TestInlineQueryResultCachedDocumentBase):
|
class TestInlineQueryResultCachedDocumentWithoutRequest(InlineQueryResultCachedDocumentTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_document):
|
def test_slot_behaviour(self, inline_query_result_cached_document):
|
||||||
inst = inline_query_result_cached_document
|
inst = inline_query_result_cached_document
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,19 +32,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_gif():
|
def inline_query_result_cached_gif():
|
||||||
return InlineQueryResultCachedGif(
|
return InlineQueryResultCachedGif(
|
||||||
TestInlineQueryResultCachedGifBase.id_,
|
InlineQueryResultCachedGifTestBase.id_,
|
||||||
TestInlineQueryResultCachedGifBase.gif_file_id,
|
InlineQueryResultCachedGifTestBase.gif_file_id,
|
||||||
title=TestInlineQueryResultCachedGifBase.title,
|
title=InlineQueryResultCachedGifTestBase.title,
|
||||||
caption=TestInlineQueryResultCachedGifBase.caption,
|
caption=InlineQueryResultCachedGifTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedGifBase.parse_mode,
|
parse_mode=InlineQueryResultCachedGifTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedGifBase.caption_entities,
|
caption_entities=InlineQueryResultCachedGifTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultCachedGifBase.input_message_content,
|
input_message_content=InlineQueryResultCachedGifTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedGifBase.reply_markup,
|
reply_markup=InlineQueryResultCachedGifTestBase.reply_markup,
|
||||||
show_caption_above_media=TestInlineQueryResultCachedGifBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultCachedGifTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedGifBase:
|
class InlineQueryResultCachedGifTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "gif"
|
type_ = "gif"
|
||||||
gif_file_id = "gif file id"
|
gif_file_id = "gif file id"
|
||||||
|
@ -57,7 +57,7 @@ class TestInlineQueryResultCachedGifBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedGifWithoutRequest(TestInlineQueryResultCachedGifBase):
|
class TestInlineQueryResultCachedGifWithoutRequest(InlineQueryResultCachedGifTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_gif):
|
def test_slot_behaviour(self, inline_query_result_cached_gif):
|
||||||
inst = inline_query_result_cached_gif
|
inst = inline_query_result_cached_gif
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,19 +32,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_mpeg4_gif():
|
def inline_query_result_cached_mpeg4_gif():
|
||||||
return InlineQueryResultCachedMpeg4Gif(
|
return InlineQueryResultCachedMpeg4Gif(
|
||||||
TestInlineQueryResultCachedMpeg4GifBase.id_,
|
InlineQueryResultCachedMpeg4GifTestBase.id_,
|
||||||
TestInlineQueryResultCachedMpeg4GifBase.mpeg4_file_id,
|
InlineQueryResultCachedMpeg4GifTestBase.mpeg4_file_id,
|
||||||
title=TestInlineQueryResultCachedMpeg4GifBase.title,
|
title=InlineQueryResultCachedMpeg4GifTestBase.title,
|
||||||
caption=TestInlineQueryResultCachedMpeg4GifBase.caption,
|
caption=InlineQueryResultCachedMpeg4GifTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedMpeg4GifBase.parse_mode,
|
parse_mode=InlineQueryResultCachedMpeg4GifTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedMpeg4GifBase.caption_entities,
|
caption_entities=InlineQueryResultCachedMpeg4GifTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultCachedMpeg4GifBase.input_message_content,
|
input_message_content=InlineQueryResultCachedMpeg4GifTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedMpeg4GifBase.reply_markup,
|
reply_markup=InlineQueryResultCachedMpeg4GifTestBase.reply_markup,
|
||||||
show_caption_above_media=TestInlineQueryResultCachedMpeg4GifBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultCachedMpeg4GifTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedMpeg4GifBase:
|
class InlineQueryResultCachedMpeg4GifTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "mpeg4_gif"
|
type_ = "mpeg4_gif"
|
||||||
mpeg4_file_id = "mpeg4 file id"
|
mpeg4_file_id = "mpeg4 file id"
|
||||||
|
@ -57,7 +57,7 @@ class TestInlineQueryResultCachedMpeg4GifBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedMpeg4GifWithoutRequest(TestInlineQueryResultCachedMpeg4GifBase):
|
class TestInlineQueryResultCachedMpeg4GifWithoutRequest(InlineQueryResultCachedMpeg4GifTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_mpeg4_gif):
|
def test_slot_behaviour(self, inline_query_result_cached_mpeg4_gif):
|
||||||
inst = inline_query_result_cached_mpeg4_gif
|
inst = inline_query_result_cached_mpeg4_gif
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,20 +32,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_photo():
|
def inline_query_result_cached_photo():
|
||||||
return InlineQueryResultCachedPhoto(
|
return InlineQueryResultCachedPhoto(
|
||||||
TestInlineQueryResultCachedPhotoBase.id_,
|
InlineQueryResultCachedPhotoTestBase.id_,
|
||||||
TestInlineQueryResultCachedPhotoBase.photo_file_id,
|
InlineQueryResultCachedPhotoTestBase.photo_file_id,
|
||||||
title=TestInlineQueryResultCachedPhotoBase.title,
|
title=InlineQueryResultCachedPhotoTestBase.title,
|
||||||
description=TestInlineQueryResultCachedPhotoBase.description,
|
description=InlineQueryResultCachedPhotoTestBase.description,
|
||||||
caption=TestInlineQueryResultCachedPhotoBase.caption,
|
caption=InlineQueryResultCachedPhotoTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedPhotoBase.parse_mode,
|
parse_mode=InlineQueryResultCachedPhotoTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedPhotoBase.caption_entities,
|
caption_entities=InlineQueryResultCachedPhotoTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultCachedPhotoBase.input_message_content,
|
input_message_content=InlineQueryResultCachedPhotoTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedPhotoBase.reply_markup,
|
reply_markup=InlineQueryResultCachedPhotoTestBase.reply_markup,
|
||||||
show_caption_above_media=TestInlineQueryResultCachedPhotoBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultCachedPhotoTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedPhotoBase:
|
class InlineQueryResultCachedPhotoTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "photo"
|
type_ = "photo"
|
||||||
photo_file_id = "photo file id"
|
photo_file_id = "photo file id"
|
||||||
|
@ -59,7 +59,7 @@ class TestInlineQueryResultCachedPhotoBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedPhotoWithoutRequest(TestInlineQueryResultCachedPhotoBase):
|
class TestInlineQueryResultCachedPhotoWithoutRequest(InlineQueryResultCachedPhotoTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_photo):
|
def test_slot_behaviour(self, inline_query_result_cached_photo):
|
||||||
inst = inline_query_result_cached_photo
|
inst = inline_query_result_cached_photo
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -31,14 +31,14 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_sticker():
|
def inline_query_result_cached_sticker():
|
||||||
return InlineQueryResultCachedSticker(
|
return InlineQueryResultCachedSticker(
|
||||||
TestInlineQueryResultCachedStickerBase.id_,
|
InlineQueryResultCachedStickerTestBase.id_,
|
||||||
TestInlineQueryResultCachedStickerBase.sticker_file_id,
|
InlineQueryResultCachedStickerTestBase.sticker_file_id,
|
||||||
input_message_content=TestInlineQueryResultCachedStickerBase.input_message_content,
|
input_message_content=InlineQueryResultCachedStickerTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedStickerBase.reply_markup,
|
reply_markup=InlineQueryResultCachedStickerTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedStickerBase:
|
class InlineQueryResultCachedStickerTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "sticker"
|
type_ = "sticker"
|
||||||
sticker_file_id = "sticker file id"
|
sticker_file_id = "sticker file id"
|
||||||
|
@ -46,7 +46,7 @@ class TestInlineQueryResultCachedStickerBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedStickerWithoutRequest(TestInlineQueryResultCachedStickerBase):
|
class TestInlineQueryResultCachedStickerWithoutRequest(InlineQueryResultCachedStickerTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_sticker):
|
def test_slot_behaviour(self, inline_query_result_cached_sticker):
|
||||||
inst = inline_query_result_cached_sticker
|
inst = inline_query_result_cached_sticker
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,20 +32,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_video():
|
def inline_query_result_cached_video():
|
||||||
return InlineQueryResultCachedVideo(
|
return InlineQueryResultCachedVideo(
|
||||||
TestInlineQueryResultCachedVideoBase.id_,
|
InlineQueryResultCachedVideoTestBase.id_,
|
||||||
TestInlineQueryResultCachedVideoBase.video_file_id,
|
InlineQueryResultCachedVideoTestBase.video_file_id,
|
||||||
TestInlineQueryResultCachedVideoBase.title,
|
InlineQueryResultCachedVideoTestBase.title,
|
||||||
caption=TestInlineQueryResultCachedVideoBase.caption,
|
caption=InlineQueryResultCachedVideoTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedVideoBase.parse_mode,
|
parse_mode=InlineQueryResultCachedVideoTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedVideoBase.caption_entities,
|
caption_entities=InlineQueryResultCachedVideoTestBase.caption_entities,
|
||||||
description=TestInlineQueryResultCachedVideoBase.description,
|
description=InlineQueryResultCachedVideoTestBase.description,
|
||||||
input_message_content=TestInlineQueryResultCachedVideoBase.input_message_content,
|
input_message_content=InlineQueryResultCachedVideoTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedVideoBase.reply_markup,
|
reply_markup=InlineQueryResultCachedVideoTestBase.reply_markup,
|
||||||
show_caption_above_media=TestInlineQueryResultCachedVideoBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultCachedVideoTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedVideoBase:
|
class InlineQueryResultCachedVideoTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "video"
|
type_ = "video"
|
||||||
video_file_id = "video file id"
|
video_file_id = "video file id"
|
||||||
|
@ -59,7 +59,7 @@ class TestInlineQueryResultCachedVideoBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedVideoWithoutRequest(TestInlineQueryResultCachedVideoBase):
|
class TestInlineQueryResultCachedVideoWithoutRequest(InlineQueryResultCachedVideoTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_video):
|
def test_slot_behaviour(self, inline_query_result_cached_video):
|
||||||
inst = inline_query_result_cached_video
|
inst = inline_query_result_cached_video
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,18 +32,18 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_cached_voice():
|
def inline_query_result_cached_voice():
|
||||||
return InlineQueryResultCachedVoice(
|
return InlineQueryResultCachedVoice(
|
||||||
TestInlineQueryResultCachedVoiceBase.id_,
|
InlineQueryResultCachedVoiceTestBase.id_,
|
||||||
TestInlineQueryResultCachedVoiceBase.voice_file_id,
|
InlineQueryResultCachedVoiceTestBase.voice_file_id,
|
||||||
TestInlineQueryResultCachedVoiceBase.title,
|
InlineQueryResultCachedVoiceTestBase.title,
|
||||||
caption=TestInlineQueryResultCachedVoiceBase.caption,
|
caption=InlineQueryResultCachedVoiceTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultCachedVoiceBase.parse_mode,
|
parse_mode=InlineQueryResultCachedVoiceTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultCachedVoiceBase.caption_entities,
|
caption_entities=InlineQueryResultCachedVoiceTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultCachedVoiceBase.input_message_content,
|
input_message_content=InlineQueryResultCachedVoiceTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultCachedVoiceBase.reply_markup,
|
reply_markup=InlineQueryResultCachedVoiceTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedVoiceBase:
|
class InlineQueryResultCachedVoiceTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "voice"
|
type_ = "voice"
|
||||||
voice_file_id = "voice file id"
|
voice_file_id = "voice file id"
|
||||||
|
@ -55,7 +55,7 @@ class TestInlineQueryResultCachedVoiceBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultCachedVoiceWithoutRequest(TestInlineQueryResultCachedVoiceBase):
|
class TestInlineQueryResultCachedVoiceWithoutRequest(InlineQueryResultCachedVoiceTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_cached_voice):
|
def test_slot_behaviour(self, inline_query_result_cached_voice):
|
||||||
inst = inline_query_result_cached_voice
|
inst = inline_query_result_cached_voice
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -31,19 +31,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_contact():
|
def inline_query_result_contact():
|
||||||
return InlineQueryResultContact(
|
return InlineQueryResultContact(
|
||||||
TestInlineQueryResultContactBase.id_,
|
InlineQueryResultContactTestBase.id_,
|
||||||
TestInlineQueryResultContactBase.phone_number,
|
InlineQueryResultContactTestBase.phone_number,
|
||||||
TestInlineQueryResultContactBase.first_name,
|
InlineQueryResultContactTestBase.first_name,
|
||||||
last_name=TestInlineQueryResultContactBase.last_name,
|
last_name=InlineQueryResultContactTestBase.last_name,
|
||||||
thumbnail_url=TestInlineQueryResultContactBase.thumbnail_url,
|
thumbnail_url=InlineQueryResultContactTestBase.thumbnail_url,
|
||||||
thumbnail_width=TestInlineQueryResultContactBase.thumbnail_width,
|
thumbnail_width=InlineQueryResultContactTestBase.thumbnail_width,
|
||||||
thumbnail_height=TestInlineQueryResultContactBase.thumbnail_height,
|
thumbnail_height=InlineQueryResultContactTestBase.thumbnail_height,
|
||||||
input_message_content=TestInlineQueryResultContactBase.input_message_content,
|
input_message_content=InlineQueryResultContactTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultContactBase.reply_markup,
|
reply_markup=InlineQueryResultContactTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultContactBase:
|
class InlineQueryResultContactTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "contact"
|
type_ = "contact"
|
||||||
phone_number = "phone_number"
|
phone_number = "phone_number"
|
||||||
|
@ -56,7 +56,7 @@ class TestInlineQueryResultContactBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultContactWithoutRequest(TestInlineQueryResultContactBase):
|
class TestInlineQueryResultContactWithoutRequest(InlineQueryResultContactTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_contact):
|
def test_slot_behaviour(self, inline_query_result_contact):
|
||||||
inst = inline_query_result_contact
|
inst = inline_query_result_contact
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,23 +32,23 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_document():
|
def inline_query_result_document():
|
||||||
return InlineQueryResultDocument(
|
return InlineQueryResultDocument(
|
||||||
TestInlineQueryResultDocumentBase.id_,
|
InlineQueryResultDocumentTestBase.id_,
|
||||||
TestInlineQueryResultDocumentBase.document_url,
|
InlineQueryResultDocumentTestBase.document_url,
|
||||||
TestInlineQueryResultDocumentBase.title,
|
InlineQueryResultDocumentTestBase.title,
|
||||||
TestInlineQueryResultDocumentBase.mime_type,
|
InlineQueryResultDocumentTestBase.mime_type,
|
||||||
caption=TestInlineQueryResultDocumentBase.caption,
|
caption=InlineQueryResultDocumentTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultDocumentBase.parse_mode,
|
parse_mode=InlineQueryResultDocumentTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultDocumentBase.caption_entities,
|
caption_entities=InlineQueryResultDocumentTestBase.caption_entities,
|
||||||
description=TestInlineQueryResultDocumentBase.description,
|
description=InlineQueryResultDocumentTestBase.description,
|
||||||
thumbnail_url=TestInlineQueryResultDocumentBase.thumbnail_url,
|
thumbnail_url=InlineQueryResultDocumentTestBase.thumbnail_url,
|
||||||
thumbnail_width=TestInlineQueryResultDocumentBase.thumbnail_width,
|
thumbnail_width=InlineQueryResultDocumentTestBase.thumbnail_width,
|
||||||
thumbnail_height=TestInlineQueryResultDocumentBase.thumbnail_height,
|
thumbnail_height=InlineQueryResultDocumentTestBase.thumbnail_height,
|
||||||
input_message_content=TestInlineQueryResultDocumentBase.input_message_content,
|
input_message_content=InlineQueryResultDocumentTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultDocumentBase.reply_markup,
|
reply_markup=InlineQueryResultDocumentTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultDocumentBase:
|
class InlineQueryResultDocumentTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "document"
|
type_ = "document"
|
||||||
document_url = "document url"
|
document_url = "document url"
|
||||||
|
@ -65,7 +65,7 @@ class TestInlineQueryResultDocumentBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultDocumentWithoutRequest(TestInlineQueryResultDocumentBase):
|
class TestInlineQueryResultDocumentWithoutRequest(InlineQueryResultDocumentTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_document):
|
def test_slot_behaviour(self, inline_query_result_document):
|
||||||
inst = inline_query_result_document
|
inst = inline_query_result_document
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -30,20 +30,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_game():
|
def inline_query_result_game():
|
||||||
return InlineQueryResultGame(
|
return InlineQueryResultGame(
|
||||||
TestInlineQueryResultGameBase.id_,
|
InlineQueryResultGameTestBase.id_,
|
||||||
TestInlineQueryResultGameBase.game_short_name,
|
InlineQueryResultGameTestBase.game_short_name,
|
||||||
reply_markup=TestInlineQueryResultGameBase.reply_markup,
|
reply_markup=InlineQueryResultGameTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultGameBase:
|
class InlineQueryResultGameTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "game"
|
type_ = "game"
|
||||||
game_short_name = "game short name"
|
game_short_name = "game short name"
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultGameWithoutRequest(TestInlineQueryResultGameBase):
|
class TestInlineQueryResultGameWithoutRequest(InlineQueryResultGameTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_game):
|
def test_slot_behaviour(self, inline_query_result_game):
|
||||||
inst = inline_query_result_game
|
inst = inline_query_result_game
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,24 +32,24 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_gif():
|
def inline_query_result_gif():
|
||||||
return InlineQueryResultGif(
|
return InlineQueryResultGif(
|
||||||
TestInlineQueryResultGifBase.id_,
|
InlineQueryResultGifTestBase.id_,
|
||||||
TestInlineQueryResultGifBase.gif_url,
|
InlineQueryResultGifTestBase.gif_url,
|
||||||
TestInlineQueryResultGifBase.thumbnail_url,
|
InlineQueryResultGifTestBase.thumbnail_url,
|
||||||
gif_width=TestInlineQueryResultGifBase.gif_width,
|
gif_width=InlineQueryResultGifTestBase.gif_width,
|
||||||
gif_height=TestInlineQueryResultGifBase.gif_height,
|
gif_height=InlineQueryResultGifTestBase.gif_height,
|
||||||
gif_duration=TestInlineQueryResultGifBase.gif_duration,
|
gif_duration=InlineQueryResultGifTestBase.gif_duration,
|
||||||
title=TestInlineQueryResultGifBase.title,
|
title=InlineQueryResultGifTestBase.title,
|
||||||
caption=TestInlineQueryResultGifBase.caption,
|
caption=InlineQueryResultGifTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultGifBase.parse_mode,
|
parse_mode=InlineQueryResultGifTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultGifBase.caption_entities,
|
caption_entities=InlineQueryResultGifTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultGifBase.input_message_content,
|
input_message_content=InlineQueryResultGifTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultGifBase.reply_markup,
|
reply_markup=InlineQueryResultGifTestBase.reply_markup,
|
||||||
thumbnail_mime_type=TestInlineQueryResultGifBase.thumbnail_mime_type,
|
thumbnail_mime_type=InlineQueryResultGifTestBase.thumbnail_mime_type,
|
||||||
show_caption_above_media=TestInlineQueryResultGifBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultGifTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultGifBase:
|
class InlineQueryResultGifTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "gif"
|
type_ = "gif"
|
||||||
gif_url = "gif url"
|
gif_url = "gif url"
|
||||||
|
@ -67,7 +67,7 @@ class TestInlineQueryResultGifBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultGifWithoutRequest(TestInlineQueryResultGifBase):
|
class TestInlineQueryResultGifWithoutRequest(InlineQueryResultGifTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_gif):
|
def test_slot_behaviour(self, inline_query_result_gif):
|
||||||
inst = inline_query_result_gif
|
inst = inline_query_result_gif
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -31,23 +31,23 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_location():
|
def inline_query_result_location():
|
||||||
return InlineQueryResultLocation(
|
return InlineQueryResultLocation(
|
||||||
TestInlineQueryResultLocationBase.id_,
|
InlineQueryResultLocationTestBase.id_,
|
||||||
TestInlineQueryResultLocationBase.latitude,
|
InlineQueryResultLocationTestBase.latitude,
|
||||||
TestInlineQueryResultLocationBase.longitude,
|
InlineQueryResultLocationTestBase.longitude,
|
||||||
TestInlineQueryResultLocationBase.title,
|
InlineQueryResultLocationTestBase.title,
|
||||||
live_period=TestInlineQueryResultLocationBase.live_period,
|
live_period=InlineQueryResultLocationTestBase.live_period,
|
||||||
thumbnail_url=TestInlineQueryResultLocationBase.thumbnail_url,
|
thumbnail_url=InlineQueryResultLocationTestBase.thumbnail_url,
|
||||||
thumbnail_width=TestInlineQueryResultLocationBase.thumbnail_width,
|
thumbnail_width=InlineQueryResultLocationTestBase.thumbnail_width,
|
||||||
thumbnail_height=TestInlineQueryResultLocationBase.thumbnail_height,
|
thumbnail_height=InlineQueryResultLocationTestBase.thumbnail_height,
|
||||||
input_message_content=TestInlineQueryResultLocationBase.input_message_content,
|
input_message_content=InlineQueryResultLocationTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultLocationBase.reply_markup,
|
reply_markup=InlineQueryResultLocationTestBase.reply_markup,
|
||||||
horizontal_accuracy=TestInlineQueryResultLocationBase.horizontal_accuracy,
|
horizontal_accuracy=InlineQueryResultLocationTestBase.horizontal_accuracy,
|
||||||
heading=TestInlineQueryResultLocationBase.heading,
|
heading=InlineQueryResultLocationTestBase.heading,
|
||||||
proximity_alert_radius=TestInlineQueryResultLocationBase.proximity_alert_radius,
|
proximity_alert_radius=InlineQueryResultLocationTestBase.proximity_alert_radius,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultLocationBase:
|
class InlineQueryResultLocationTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "location"
|
type_ = "location"
|
||||||
latitude = 0.0
|
latitude = 0.0
|
||||||
|
@ -64,7 +64,7 @@ class TestInlineQueryResultLocationBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultLocationWithoutRequest(TestInlineQueryResultLocationBase):
|
class TestInlineQueryResultLocationWithoutRequest(InlineQueryResultLocationTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_location):
|
def test_slot_behaviour(self, inline_query_result_location):
|
||||||
inst = inline_query_result_location
|
inst = inline_query_result_location
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,24 +32,24 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_mpeg4_gif():
|
def inline_query_result_mpeg4_gif():
|
||||||
return InlineQueryResultMpeg4Gif(
|
return InlineQueryResultMpeg4Gif(
|
||||||
TestInlineQueryResultMpeg4GifBase.id_,
|
InlineQueryResultMpeg4GifTestBase.id_,
|
||||||
TestInlineQueryResultMpeg4GifBase.mpeg4_url,
|
InlineQueryResultMpeg4GifTestBase.mpeg4_url,
|
||||||
TestInlineQueryResultMpeg4GifBase.thumbnail_url,
|
InlineQueryResultMpeg4GifTestBase.thumbnail_url,
|
||||||
mpeg4_width=TestInlineQueryResultMpeg4GifBase.mpeg4_width,
|
mpeg4_width=InlineQueryResultMpeg4GifTestBase.mpeg4_width,
|
||||||
mpeg4_height=TestInlineQueryResultMpeg4GifBase.mpeg4_height,
|
mpeg4_height=InlineQueryResultMpeg4GifTestBase.mpeg4_height,
|
||||||
mpeg4_duration=TestInlineQueryResultMpeg4GifBase.mpeg4_duration,
|
mpeg4_duration=InlineQueryResultMpeg4GifTestBase.mpeg4_duration,
|
||||||
title=TestInlineQueryResultMpeg4GifBase.title,
|
title=InlineQueryResultMpeg4GifTestBase.title,
|
||||||
caption=TestInlineQueryResultMpeg4GifBase.caption,
|
caption=InlineQueryResultMpeg4GifTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultMpeg4GifBase.parse_mode,
|
parse_mode=InlineQueryResultMpeg4GifTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultMpeg4GifBase.caption_entities,
|
caption_entities=InlineQueryResultMpeg4GifTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultMpeg4GifBase.input_message_content,
|
input_message_content=InlineQueryResultMpeg4GifTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultMpeg4GifBase.reply_markup,
|
reply_markup=InlineQueryResultMpeg4GifTestBase.reply_markup,
|
||||||
thumbnail_mime_type=TestInlineQueryResultMpeg4GifBase.thumbnail_mime_type,
|
thumbnail_mime_type=InlineQueryResultMpeg4GifTestBase.thumbnail_mime_type,
|
||||||
show_caption_above_media=TestInlineQueryResultMpeg4GifBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultMpeg4GifTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultMpeg4GifBase:
|
class InlineQueryResultMpeg4GifTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "mpeg4_gif"
|
type_ = "mpeg4_gif"
|
||||||
mpeg4_url = "mpeg4 url"
|
mpeg4_url = "mpeg4 url"
|
||||||
|
@ -67,7 +67,7 @@ class TestInlineQueryResultMpeg4GifBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultMpeg4GifWithoutRequest(TestInlineQueryResultMpeg4GifBase):
|
class TestInlineQueryResultMpeg4GifWithoutRequest(InlineQueryResultMpeg4GifTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_mpeg4_gif):
|
def test_slot_behaviour(self, inline_query_result_mpeg4_gif):
|
||||||
inst = inline_query_result_mpeg4_gif
|
inst = inline_query_result_mpeg4_gif
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,23 +32,23 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_photo():
|
def inline_query_result_photo():
|
||||||
return InlineQueryResultPhoto(
|
return InlineQueryResultPhoto(
|
||||||
TestInlineQueryResultPhotoBase.id_,
|
InlineQueryResultPhotoTestBase.id_,
|
||||||
TestInlineQueryResultPhotoBase.photo_url,
|
InlineQueryResultPhotoTestBase.photo_url,
|
||||||
TestInlineQueryResultPhotoBase.thumbnail_url,
|
InlineQueryResultPhotoTestBase.thumbnail_url,
|
||||||
photo_width=TestInlineQueryResultPhotoBase.photo_width,
|
photo_width=InlineQueryResultPhotoTestBase.photo_width,
|
||||||
photo_height=TestInlineQueryResultPhotoBase.photo_height,
|
photo_height=InlineQueryResultPhotoTestBase.photo_height,
|
||||||
title=TestInlineQueryResultPhotoBase.title,
|
title=InlineQueryResultPhotoTestBase.title,
|
||||||
description=TestInlineQueryResultPhotoBase.description,
|
description=InlineQueryResultPhotoTestBase.description,
|
||||||
caption=TestInlineQueryResultPhotoBase.caption,
|
caption=InlineQueryResultPhotoTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultPhotoBase.parse_mode,
|
parse_mode=InlineQueryResultPhotoTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultPhotoBase.caption_entities,
|
caption_entities=InlineQueryResultPhotoTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultPhotoBase.input_message_content,
|
input_message_content=InlineQueryResultPhotoTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultPhotoBase.reply_markup,
|
reply_markup=InlineQueryResultPhotoTestBase.reply_markup,
|
||||||
show_caption_above_media=TestInlineQueryResultPhotoBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultPhotoTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultPhotoBase:
|
class InlineQueryResultPhotoTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "photo"
|
type_ = "photo"
|
||||||
photo_url = "photo url"
|
photo_url = "photo url"
|
||||||
|
@ -66,7 +66,7 @@ class TestInlineQueryResultPhotoBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultPhotoWithoutRequest(TestInlineQueryResultPhotoBase):
|
class TestInlineQueryResultPhotoWithoutRequest(InlineQueryResultPhotoTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_photo):
|
def test_slot_behaviour(self, inline_query_result_photo):
|
||||||
inst = inline_query_result_photo
|
inst = inline_query_result_photo
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -31,24 +31,24 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_venue():
|
def inline_query_result_venue():
|
||||||
return InlineQueryResultVenue(
|
return InlineQueryResultVenue(
|
||||||
TestInlineQueryResultVenueBase.id_,
|
InlineQueryResultVenueTestBase.id_,
|
||||||
TestInlineQueryResultVenueBase.latitude,
|
InlineQueryResultVenueTestBase.latitude,
|
||||||
TestInlineQueryResultVenueBase.longitude,
|
InlineQueryResultVenueTestBase.longitude,
|
||||||
TestInlineQueryResultVenueBase.title,
|
InlineQueryResultVenueTestBase.title,
|
||||||
TestInlineQueryResultVenueBase.address,
|
InlineQueryResultVenueTestBase.address,
|
||||||
foursquare_id=TestInlineQueryResultVenueBase.foursquare_id,
|
foursquare_id=InlineQueryResultVenueTestBase.foursquare_id,
|
||||||
foursquare_type=TestInlineQueryResultVenueBase.foursquare_type,
|
foursquare_type=InlineQueryResultVenueTestBase.foursquare_type,
|
||||||
thumbnail_url=TestInlineQueryResultVenueBase.thumbnail_url,
|
thumbnail_url=InlineQueryResultVenueTestBase.thumbnail_url,
|
||||||
thumbnail_width=TestInlineQueryResultVenueBase.thumbnail_width,
|
thumbnail_width=InlineQueryResultVenueTestBase.thumbnail_width,
|
||||||
thumbnail_height=TestInlineQueryResultVenueBase.thumbnail_height,
|
thumbnail_height=InlineQueryResultVenueTestBase.thumbnail_height,
|
||||||
input_message_content=TestInlineQueryResultVenueBase.input_message_content,
|
input_message_content=InlineQueryResultVenueTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultVenueBase.reply_markup,
|
reply_markup=InlineQueryResultVenueTestBase.reply_markup,
|
||||||
google_place_id=TestInlineQueryResultVenueBase.google_place_id,
|
google_place_id=InlineQueryResultVenueTestBase.google_place_id,
|
||||||
google_place_type=TestInlineQueryResultVenueBase.google_place_type,
|
google_place_type=InlineQueryResultVenueTestBase.google_place_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultVenueBase:
|
class InlineQueryResultVenueTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "venue"
|
type_ = "venue"
|
||||||
latitude = "latitude"
|
latitude = "latitude"
|
||||||
|
@ -66,7 +66,7 @@ class TestInlineQueryResultVenueBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultVenueWithoutRequest(TestInlineQueryResultVenueBase):
|
class TestInlineQueryResultVenueWithoutRequest(InlineQueryResultVenueTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_venue):
|
def test_slot_behaviour(self, inline_query_result_venue):
|
||||||
inst = inline_query_result_venue
|
inst = inline_query_result_venue
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,25 +32,25 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_video():
|
def inline_query_result_video():
|
||||||
return InlineQueryResultVideo(
|
return InlineQueryResultVideo(
|
||||||
TestInlineQueryResultVideoBase.id_,
|
InlineQueryResultVideoTestBase.id_,
|
||||||
TestInlineQueryResultVideoBase.video_url,
|
InlineQueryResultVideoTestBase.video_url,
|
||||||
TestInlineQueryResultVideoBase.mime_type,
|
InlineQueryResultVideoTestBase.mime_type,
|
||||||
TestInlineQueryResultVideoBase.thumbnail_url,
|
InlineQueryResultVideoTestBase.thumbnail_url,
|
||||||
TestInlineQueryResultVideoBase.title,
|
InlineQueryResultVideoTestBase.title,
|
||||||
video_width=TestInlineQueryResultVideoBase.video_width,
|
video_width=InlineQueryResultVideoTestBase.video_width,
|
||||||
video_height=TestInlineQueryResultVideoBase.video_height,
|
video_height=InlineQueryResultVideoTestBase.video_height,
|
||||||
video_duration=TestInlineQueryResultVideoBase.video_duration,
|
video_duration=InlineQueryResultVideoTestBase.video_duration,
|
||||||
caption=TestInlineQueryResultVideoBase.caption,
|
caption=InlineQueryResultVideoTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultVideoBase.parse_mode,
|
parse_mode=InlineQueryResultVideoTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultVideoBase.caption_entities,
|
caption_entities=InlineQueryResultVideoTestBase.caption_entities,
|
||||||
description=TestInlineQueryResultVideoBase.description,
|
description=InlineQueryResultVideoTestBase.description,
|
||||||
input_message_content=TestInlineQueryResultVideoBase.input_message_content,
|
input_message_content=InlineQueryResultVideoTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultVideoBase.reply_markup,
|
reply_markup=InlineQueryResultVideoTestBase.reply_markup,
|
||||||
show_caption_above_media=TestInlineQueryResultVideoBase.show_caption_above_media,
|
show_caption_above_media=InlineQueryResultVideoTestBase.show_caption_above_media,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultVideoBase:
|
class InlineQueryResultVideoTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "video"
|
type_ = "video"
|
||||||
video_url = "video url"
|
video_url = "video url"
|
||||||
|
@ -69,7 +69,7 @@ class TestInlineQueryResultVideoBase:
|
||||||
show_caption_above_media = True
|
show_caption_above_media = True
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultVideoWithoutRequest(TestInlineQueryResultVideoBase):
|
class TestInlineQueryResultVideoWithoutRequest(InlineQueryResultVideoTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_video):
|
def test_slot_behaviour(self, inline_query_result_video):
|
||||||
inst = inline_query_result_video
|
inst = inline_query_result_video
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -32,19 +32,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def inline_query_result_voice():
|
def inline_query_result_voice():
|
||||||
return InlineQueryResultVoice(
|
return InlineQueryResultVoice(
|
||||||
id=TestInlineQueryResultVoiceBase.id_,
|
id=InlineQueryResultVoiceTestBase.id_,
|
||||||
voice_url=TestInlineQueryResultVoiceBase.voice_url,
|
voice_url=InlineQueryResultVoiceTestBase.voice_url,
|
||||||
title=TestInlineQueryResultVoiceBase.title,
|
title=InlineQueryResultVoiceTestBase.title,
|
||||||
voice_duration=TestInlineQueryResultVoiceBase.voice_duration,
|
voice_duration=InlineQueryResultVoiceTestBase.voice_duration,
|
||||||
caption=TestInlineQueryResultVoiceBase.caption,
|
caption=InlineQueryResultVoiceTestBase.caption,
|
||||||
parse_mode=TestInlineQueryResultVoiceBase.parse_mode,
|
parse_mode=InlineQueryResultVoiceTestBase.parse_mode,
|
||||||
caption_entities=TestInlineQueryResultVoiceBase.caption_entities,
|
caption_entities=InlineQueryResultVoiceTestBase.caption_entities,
|
||||||
input_message_content=TestInlineQueryResultVoiceBase.input_message_content,
|
input_message_content=InlineQueryResultVoiceTestBase.input_message_content,
|
||||||
reply_markup=TestInlineQueryResultVoiceBase.reply_markup,
|
reply_markup=InlineQueryResultVoiceTestBase.reply_markup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultVoiceBase:
|
class InlineQueryResultVoiceTestBase:
|
||||||
id_ = "id"
|
id_ = "id"
|
||||||
type_ = "voice"
|
type_ = "voice"
|
||||||
voice_url = "voice url"
|
voice_url = "voice url"
|
||||||
|
@ -57,7 +57,7 @@ class TestInlineQueryResultVoiceBase:
|
||||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||||
|
|
||||||
|
|
||||||
class TestInlineQueryResultVoiceWithoutRequest(TestInlineQueryResultVoiceBase):
|
class TestInlineQueryResultVoiceWithoutRequest(InlineQueryResultVoiceTestBase):
|
||||||
def test_slot_behaviour(self, inline_query_result_voice):
|
def test_slot_behaviour(self, inline_query_result_voice):
|
||||||
inst = inline_query_result_voice
|
inst = inline_query_result_voice
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,19 +25,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_contact_message_content():
|
def input_contact_message_content():
|
||||||
return InputContactMessageContent(
|
return InputContactMessageContent(
|
||||||
TestInputContactMessageContentBase.phone_number,
|
InputContactMessageContentTestBase.phone_number,
|
||||||
TestInputContactMessageContentBase.first_name,
|
InputContactMessageContentTestBase.first_name,
|
||||||
TestInputContactMessageContentBase.last_name,
|
InputContactMessageContentTestBase.last_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputContactMessageContentBase:
|
class InputContactMessageContentTestBase:
|
||||||
phone_number = "phone number"
|
phone_number = "phone number"
|
||||||
first_name = "first name"
|
first_name = "first name"
|
||||||
last_name = "last name"
|
last_name = "last name"
|
||||||
|
|
||||||
|
|
||||||
class TestInputContactMessageContentWithoutRequest(TestInputContactMessageContentBase):
|
class TestInputContactMessageContentWithoutRequest(InputContactMessageContentTestBase):
|
||||||
def test_slot_behaviour(self, input_contact_message_content):
|
def test_slot_behaviour(self, input_contact_message_content):
|
||||||
inst = input_contact_message_content
|
inst = input_contact_message_content
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -26,32 +26,32 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_invoice_message_content():
|
def input_invoice_message_content():
|
||||||
return InputInvoiceMessageContent(
|
return InputInvoiceMessageContent(
|
||||||
title=TestInputInvoiceMessageContentBase.title,
|
title=InputInvoiceMessageContentTestBase.title,
|
||||||
description=TestInputInvoiceMessageContentBase.description,
|
description=InputInvoiceMessageContentTestBase.description,
|
||||||
payload=TestInputInvoiceMessageContentBase.payload,
|
payload=InputInvoiceMessageContentTestBase.payload,
|
||||||
provider_token=TestInputInvoiceMessageContentBase.provider_token,
|
provider_token=InputInvoiceMessageContentTestBase.provider_token,
|
||||||
currency=TestInputInvoiceMessageContentBase.currency,
|
currency=InputInvoiceMessageContentTestBase.currency,
|
||||||
prices=TestInputInvoiceMessageContentBase.prices,
|
prices=InputInvoiceMessageContentTestBase.prices,
|
||||||
max_tip_amount=TestInputInvoiceMessageContentBase.max_tip_amount,
|
max_tip_amount=InputInvoiceMessageContentTestBase.max_tip_amount,
|
||||||
suggested_tip_amounts=TestInputInvoiceMessageContentBase.suggested_tip_amounts,
|
suggested_tip_amounts=InputInvoiceMessageContentTestBase.suggested_tip_amounts,
|
||||||
provider_data=TestInputInvoiceMessageContentBase.provider_data,
|
provider_data=InputInvoiceMessageContentTestBase.provider_data,
|
||||||
photo_url=TestInputInvoiceMessageContentBase.photo_url,
|
photo_url=InputInvoiceMessageContentTestBase.photo_url,
|
||||||
photo_size=TestInputInvoiceMessageContentBase.photo_size,
|
photo_size=InputInvoiceMessageContentTestBase.photo_size,
|
||||||
photo_width=TestInputInvoiceMessageContentBase.photo_width,
|
photo_width=InputInvoiceMessageContentTestBase.photo_width,
|
||||||
photo_height=TestInputInvoiceMessageContentBase.photo_height,
|
photo_height=InputInvoiceMessageContentTestBase.photo_height,
|
||||||
need_name=TestInputInvoiceMessageContentBase.need_name,
|
need_name=InputInvoiceMessageContentTestBase.need_name,
|
||||||
need_phone_number=TestInputInvoiceMessageContentBase.need_phone_number,
|
need_phone_number=InputInvoiceMessageContentTestBase.need_phone_number,
|
||||||
need_email=TestInputInvoiceMessageContentBase.need_email,
|
need_email=InputInvoiceMessageContentTestBase.need_email,
|
||||||
need_shipping_address=TestInputInvoiceMessageContentBase.need_shipping_address,
|
need_shipping_address=InputInvoiceMessageContentTestBase.need_shipping_address,
|
||||||
send_phone_number_to_provider=(
|
send_phone_number_to_provider=(
|
||||||
TestInputInvoiceMessageContentBase.send_phone_number_to_provider
|
InputInvoiceMessageContentTestBase.send_phone_number_to_provider
|
||||||
),
|
),
|
||||||
send_email_to_provider=TestInputInvoiceMessageContentBase.send_email_to_provider,
|
send_email_to_provider=InputInvoiceMessageContentTestBase.send_email_to_provider,
|
||||||
is_flexible=TestInputInvoiceMessageContentBase.is_flexible,
|
is_flexible=InputInvoiceMessageContentTestBase.is_flexible,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputInvoiceMessageContentBase:
|
class InputInvoiceMessageContentTestBase:
|
||||||
title = "invoice title"
|
title = "invoice title"
|
||||||
description = "invoice description"
|
description = "invoice description"
|
||||||
payload = "invoice payload"
|
payload = "invoice payload"
|
||||||
|
@ -74,7 +74,7 @@ class TestInputInvoiceMessageContentBase:
|
||||||
is_flexible = True
|
is_flexible = True
|
||||||
|
|
||||||
|
|
||||||
class TestInputInvoiceMessageContentWithoutRequest(TestInputInvoiceMessageContentBase):
|
class TestInputInvoiceMessageContentWithoutRequest(InputInvoiceMessageContentTestBase):
|
||||||
def test_slot_behaviour(self, input_invoice_message_content):
|
def test_slot_behaviour(self, input_invoice_message_content):
|
||||||
inst = input_invoice_message_content
|
inst = input_invoice_message_content
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,16 +25,16 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_location_message_content():
|
def input_location_message_content():
|
||||||
return InputLocationMessageContent(
|
return InputLocationMessageContent(
|
||||||
TestInputLocationMessageContentBase.latitude,
|
InputLocationMessageContentTestBase.latitude,
|
||||||
TestInputLocationMessageContentBase.longitude,
|
InputLocationMessageContentTestBase.longitude,
|
||||||
live_period=TestInputLocationMessageContentBase.live_period,
|
live_period=InputLocationMessageContentTestBase.live_period,
|
||||||
horizontal_accuracy=TestInputLocationMessageContentBase.horizontal_accuracy,
|
horizontal_accuracy=InputLocationMessageContentTestBase.horizontal_accuracy,
|
||||||
heading=TestInputLocationMessageContentBase.heading,
|
heading=InputLocationMessageContentTestBase.heading,
|
||||||
proximity_alert_radius=TestInputLocationMessageContentBase.proximity_alert_radius,
|
proximity_alert_radius=InputLocationMessageContentTestBase.proximity_alert_radius,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputLocationMessageContentBase:
|
class InputLocationMessageContentTestBase:
|
||||||
latitude = -23.691288
|
latitude = -23.691288
|
||||||
longitude = -46.788279
|
longitude = -46.788279
|
||||||
live_period = 80
|
live_period = 80
|
||||||
|
@ -43,7 +43,7 @@ class TestInputLocationMessageContentBase:
|
||||||
proximity_alert_radius = 999
|
proximity_alert_radius = 999
|
||||||
|
|
||||||
|
|
||||||
class TestInputLocationMessageContentWithoutRequest(TestInputLocationMessageContentBase):
|
class TestInputLocationMessageContentWithoutRequest(InputLocationMessageContentTestBase):
|
||||||
def test_slot_behaviour(self, input_location_message_content):
|
def test_slot_behaviour(self, input_location_message_content):
|
||||||
inst = input_location_message_content
|
inst = input_location_message_content
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -26,14 +26,14 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_text_message_content():
|
def input_text_message_content():
|
||||||
return InputTextMessageContent(
|
return InputTextMessageContent(
|
||||||
TestInputTextMessageContentBase.message_text,
|
InputTextMessageContentTestBase.message_text,
|
||||||
parse_mode=TestInputTextMessageContentBase.parse_mode,
|
parse_mode=InputTextMessageContentTestBase.parse_mode,
|
||||||
entities=TestInputTextMessageContentBase.entities,
|
entities=InputTextMessageContentTestBase.entities,
|
||||||
link_preview_options=TestInputTextMessageContentBase.link_preview_options,
|
link_preview_options=InputTextMessageContentTestBase.link_preview_options,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputTextMessageContentBase:
|
class InputTextMessageContentTestBase:
|
||||||
message_text = "*message text*"
|
message_text = "*message text*"
|
||||||
parse_mode = ParseMode.MARKDOWN
|
parse_mode = ParseMode.MARKDOWN
|
||||||
entities = [MessageEntity(MessageEntity.ITALIC, 0, 7)]
|
entities = [MessageEntity(MessageEntity.ITALIC, 0, 7)]
|
||||||
|
@ -41,7 +41,7 @@ class TestInputTextMessageContentBase:
|
||||||
link_preview_options = LinkPreviewOptions(False, url="https://python-telegram-bot.org")
|
link_preview_options = LinkPreviewOptions(False, url="https://python-telegram-bot.org")
|
||||||
|
|
||||||
|
|
||||||
class TestInputTextMessageContentWithoutRequest(TestInputTextMessageContentBase):
|
class TestInputTextMessageContentWithoutRequest(InputTextMessageContentTestBase):
|
||||||
def test_slot_behaviour(self, input_text_message_content):
|
def test_slot_behaviour(self, input_text_message_content):
|
||||||
inst = input_text_message_content
|
inst = input_text_message_content
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,18 +25,18 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def input_venue_message_content():
|
def input_venue_message_content():
|
||||||
return InputVenueMessageContent(
|
return InputVenueMessageContent(
|
||||||
TestInputVenueMessageContentBase.latitude,
|
InputVenueMessageContentTestBase.latitude,
|
||||||
TestInputVenueMessageContentBase.longitude,
|
InputVenueMessageContentTestBase.longitude,
|
||||||
TestInputVenueMessageContentBase.title,
|
InputVenueMessageContentTestBase.title,
|
||||||
TestInputVenueMessageContentBase.address,
|
InputVenueMessageContentTestBase.address,
|
||||||
foursquare_id=TestInputVenueMessageContentBase.foursquare_id,
|
foursquare_id=InputVenueMessageContentTestBase.foursquare_id,
|
||||||
foursquare_type=TestInputVenueMessageContentBase.foursquare_type,
|
foursquare_type=InputVenueMessageContentTestBase.foursquare_type,
|
||||||
google_place_id=TestInputVenueMessageContentBase.google_place_id,
|
google_place_id=InputVenueMessageContentTestBase.google_place_id,
|
||||||
google_place_type=TestInputVenueMessageContentBase.google_place_type,
|
google_place_type=InputVenueMessageContentTestBase.google_place_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestInputVenueMessageContentBase:
|
class InputVenueMessageContentTestBase:
|
||||||
latitude = 1.0
|
latitude = 1.0
|
||||||
longitude = 2.0
|
longitude = 2.0
|
||||||
title = "title"
|
title = "title"
|
||||||
|
@ -47,7 +47,7 @@ class TestInputVenueMessageContentBase:
|
||||||
google_place_type = "google place type"
|
google_place_type = "google place type"
|
||||||
|
|
||||||
|
|
||||||
class TestInputVenueMessageContentWithoutRequest(TestInputVenueMessageContentBase):
|
class TestInputVenueMessageContentWithoutRequest(InputVenueMessageContentTestBase):
|
||||||
def test_slot_behaviour(self, input_venue_message_content):
|
def test_slot_behaviour(self, input_venue_message_content):
|
||||||
inst = input_venue_message_content
|
inst = input_venue_message_content
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -26,19 +26,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def encrypted_credentials():
|
def encrypted_credentials():
|
||||||
return EncryptedCredentials(
|
return EncryptedCredentials(
|
||||||
TestEncryptedCredentialsBase.data,
|
EncryptedCredentialsTestBase.data,
|
||||||
TestEncryptedCredentialsBase.hash,
|
EncryptedCredentialsTestBase.hash,
|
||||||
TestEncryptedCredentialsBase.secret,
|
EncryptedCredentialsTestBase.secret,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestEncryptedCredentialsBase:
|
class EncryptedCredentialsTestBase:
|
||||||
data = "data"
|
data = "data"
|
||||||
hash = "hash"
|
hash = "hash"
|
||||||
secret = "secret"
|
secret = "secret"
|
||||||
|
|
||||||
|
|
||||||
class TestEncryptedCredentialsWithoutRequest(TestEncryptedCredentialsBase):
|
class TestEncryptedCredentialsWithoutRequest(EncryptedCredentialsTestBase):
|
||||||
def test_slot_behaviour(self, encrypted_credentials):
|
def test_slot_behaviour(self, encrypted_credentials):
|
||||||
inst = encrypted_credentials
|
inst = encrypted_credentials
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -26,19 +26,19 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def encrypted_passport_element():
|
def encrypted_passport_element():
|
||||||
return EncryptedPassportElement(
|
return EncryptedPassportElement(
|
||||||
TestEncryptedPassportElementBase.type_,
|
EncryptedPassportElementTestBase.type_,
|
||||||
"this is a hash",
|
"this is a hash",
|
||||||
data=TestEncryptedPassportElementBase.data,
|
data=EncryptedPassportElementTestBase.data,
|
||||||
phone_number=TestEncryptedPassportElementBase.phone_number,
|
phone_number=EncryptedPassportElementTestBase.phone_number,
|
||||||
email=TestEncryptedPassportElementBase.email,
|
email=EncryptedPassportElementTestBase.email,
|
||||||
files=TestEncryptedPassportElementBase.files,
|
files=EncryptedPassportElementTestBase.files,
|
||||||
front_side=TestEncryptedPassportElementBase.front_side,
|
front_side=EncryptedPassportElementTestBase.front_side,
|
||||||
reverse_side=TestEncryptedPassportElementBase.reverse_side,
|
reverse_side=EncryptedPassportElementTestBase.reverse_side,
|
||||||
selfie=TestEncryptedPassportElementBase.selfie,
|
selfie=EncryptedPassportElementTestBase.selfie,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestEncryptedPassportElementBase:
|
class EncryptedPassportElementTestBase:
|
||||||
type_ = "type"
|
type_ = "type"
|
||||||
hash = "this is a hash"
|
hash = "this is a hash"
|
||||||
data = "data"
|
data = "data"
|
||||||
|
@ -50,7 +50,7 @@ class TestEncryptedPassportElementBase:
|
||||||
selfie = PassportFile("file_id", 50, 0, 25)
|
selfie = PassportFile("file_id", 50, 0, 25)
|
||||||
|
|
||||||
|
|
||||||
class TestEncryptedPassportElementWithoutRequest(TestEncryptedPassportElementBase):
|
class TestEncryptedPassportElementWithoutRequest(EncryptedPassportElementTestBase):
|
||||||
def test_slot_behaviour(self, encrypted_passport_element):
|
def test_slot_behaviour(self, encrypted_passport_element):
|
||||||
inst = encrypted_passport_element
|
inst = encrypted_passport_element
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -220,7 +220,7 @@ def passport_data(bot):
|
||||||
return PassportData.de_json(RAW_PASSPORT_DATA, bot=bot)
|
return PassportData.de_json(RAW_PASSPORT_DATA, bot=bot)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportBase:
|
class PassportTestBase:
|
||||||
driver_license_selfie_file_id = "DgADBAADEQQAAkopgFNr6oi-wISRtAI"
|
driver_license_selfie_file_id = "DgADBAADEQQAAkopgFNr6oi-wISRtAI"
|
||||||
driver_license_selfie_file_unique_id = "d4e390cca57b4da5a65322b304762a12"
|
driver_license_selfie_file_unique_id = "d4e390cca57b4da5a65322b304762a12"
|
||||||
driver_license_front_side_file_id = "DgADBAADxwMAApnQgVPK2-ckL2eXVAI"
|
driver_license_front_side_file_id = "DgADBAADxwMAApnQgVPK2-ckL2eXVAI"
|
||||||
|
@ -243,7 +243,7 @@ class TestPassportBase:
|
||||||
driver_license_selfie_credentials_secret = "tivdId6RNYNsvXYPppdzrbxOBuBOr9wXRPDcCvnXU7E="
|
driver_license_selfie_credentials_secret = "tivdId6RNYNsvXYPppdzrbxOBuBOr9wXRPDcCvnXU7E="
|
||||||
|
|
||||||
|
|
||||||
class TestPassportWithoutRequest(TestPassportBase):
|
class TestPassportWithoutRequest(PassportTestBase):
|
||||||
def test_slot_behaviour(self, passport_data):
|
def test_slot_behaviour(self, passport_data):
|
||||||
inst = passport_data
|
inst = passport_data
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,14 +25,14 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_data_field():
|
def passport_element_error_data_field():
|
||||||
return PassportElementErrorDataField(
|
return PassportElementErrorDataField(
|
||||||
TestPassportElementErrorDataFieldBase.type_,
|
PassportElementErrorDataFieldTestBase.type_,
|
||||||
TestPassportElementErrorDataFieldBase.field_name,
|
PassportElementErrorDataFieldTestBase.field_name,
|
||||||
TestPassportElementErrorDataFieldBase.data_hash,
|
PassportElementErrorDataFieldTestBase.data_hash,
|
||||||
TestPassportElementErrorDataFieldBase.message,
|
PassportElementErrorDataFieldTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorDataFieldBase:
|
class PassportElementErrorDataFieldTestBase:
|
||||||
source = "data"
|
source = "data"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
field_name = "test_field"
|
field_name = "test_field"
|
||||||
|
@ -40,7 +40,7 @@ class TestPassportElementErrorDataFieldBase:
|
||||||
message = "Error message"
|
message = "Error message"
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorDataFieldWithoutRequest(TestPassportElementErrorDataFieldBase):
|
class TestPassportElementErrorDataFieldWithoutRequest(PassportElementErrorDataFieldTestBase):
|
||||||
def test_slot_behaviour(self, passport_element_error_data_field):
|
def test_slot_behaviour(self, passport_element_error_data_field):
|
||||||
inst = passport_element_error_data_field
|
inst = passport_element_error_data_field
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_file():
|
def passport_element_error_file():
|
||||||
return PassportElementErrorFile(
|
return PassportElementErrorFile(
|
||||||
TestPassportElementErrorFileBase.type_,
|
PassportElementErrorFileTestBase.type_,
|
||||||
TestPassportElementErrorFileBase.file_hash,
|
PassportElementErrorFileTestBase.file_hash,
|
||||||
TestPassportElementErrorFileBase.message,
|
PassportElementErrorFileTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorFileBase:
|
class PassportElementErrorFileTestBase:
|
||||||
source = "file"
|
source = "file"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
file_hash = "file_hash"
|
file_hash = "file_hash"
|
||||||
message = "Error message"
|
message = "Error message"
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorFileWithoutRequest(TestPassportElementErrorFileBase):
|
class TestPassportElementErrorFileWithoutRequest(PassportElementErrorFileTestBase):
|
||||||
def test_slot_behaviour(self, passport_element_error_file):
|
def test_slot_behaviour(self, passport_element_error_file):
|
||||||
inst = passport_element_error_file
|
inst = passport_element_error_file
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -26,20 +26,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_files():
|
def passport_element_error_files():
|
||||||
return PassportElementErrorFiles(
|
return PassportElementErrorFiles(
|
||||||
TestPassportElementErrorFilesBase.type_,
|
PassportElementErrorFilesTestBase.type_,
|
||||||
TestPassportElementErrorFilesBase.file_hashes,
|
PassportElementErrorFilesTestBase.file_hashes,
|
||||||
TestPassportElementErrorFilesBase.message,
|
PassportElementErrorFilesTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorFilesBase:
|
class PassportElementErrorFilesTestBase:
|
||||||
source = "files"
|
source = "files"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
file_hashes = ["hash1", "hash2"]
|
file_hashes = ["hash1", "hash2"]
|
||||||
message = "Error message"
|
message = "Error message"
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorFilesWithoutRequest(TestPassportElementErrorFilesBase):
|
class TestPassportElementErrorFilesWithoutRequest(PassportElementErrorFilesTestBase):
|
||||||
def test_slot_behaviour(self, passport_element_error_files):
|
def test_slot_behaviour(self, passport_element_error_files):
|
||||||
inst = passport_element_error_files
|
inst = passport_element_error_files
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_front_side():
|
def passport_element_error_front_side():
|
||||||
return PassportElementErrorFrontSide(
|
return PassportElementErrorFrontSide(
|
||||||
TestPassportElementErrorFrontSideBase.type_,
|
PassportElementErrorFrontSideTestBase.type_,
|
||||||
TestPassportElementErrorFrontSideBase.file_hash,
|
PassportElementErrorFrontSideTestBase.file_hash,
|
||||||
TestPassportElementErrorFrontSideBase.message,
|
PassportElementErrorFrontSideTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorFrontSideBase:
|
class PassportElementErrorFrontSideTestBase:
|
||||||
source = "front_side"
|
source = "front_side"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
file_hash = "file_hash"
|
file_hash = "file_hash"
|
||||||
message = "Error message"
|
message = "Error message"
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorFrontSideWithoutRequest(TestPassportElementErrorFrontSideBase):
|
class TestPassportElementErrorFrontSideWithoutRequest(PassportElementErrorFrontSideTestBase):
|
||||||
def test_slot_behaviour(self, passport_element_error_front_side):
|
def test_slot_behaviour(self, passport_element_error_front_side):
|
||||||
inst = passport_element_error_front_side
|
inst = passport_element_error_front_side
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_reverse_side():
|
def passport_element_error_reverse_side():
|
||||||
return PassportElementErrorReverseSide(
|
return PassportElementErrorReverseSide(
|
||||||
TestPassportElementErrorReverseSideBase.type_,
|
PassportElementErrorReverseSideTestBase.type_,
|
||||||
TestPassportElementErrorReverseSideBase.file_hash,
|
PassportElementErrorReverseSideTestBase.file_hash,
|
||||||
TestPassportElementErrorReverseSideBase.message,
|
PassportElementErrorReverseSideTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorReverseSideBase:
|
class PassportElementErrorReverseSideTestBase:
|
||||||
source = "reverse_side"
|
source = "reverse_side"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
file_hash = "file_hash"
|
file_hash = "file_hash"
|
||||||
message = "Error message"
|
message = "Error message"
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorReverseSideWithoutRequest(TestPassportElementErrorReverseSideBase):
|
class TestPassportElementErrorReverseSideWithoutRequest(PassportElementErrorReverseSideTestBase):
|
||||||
def test_slot_behaviour(self, passport_element_error_reverse_side):
|
def test_slot_behaviour(self, passport_element_error_reverse_side):
|
||||||
inst = passport_element_error_reverse_side
|
inst = passport_element_error_reverse_side
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_selfie():
|
def passport_element_error_selfie():
|
||||||
return PassportElementErrorSelfie(
|
return PassportElementErrorSelfie(
|
||||||
TestPassportElementErrorSelfieBase.type_,
|
PassportElementErrorSelfieTestBase.type_,
|
||||||
TestPassportElementErrorSelfieBase.file_hash,
|
PassportElementErrorSelfieTestBase.file_hash,
|
||||||
TestPassportElementErrorSelfieBase.message,
|
PassportElementErrorSelfieTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorSelfieBase:
|
class PassportElementErrorSelfieTestBase:
|
||||||
source = "selfie"
|
source = "selfie"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
file_hash = "file_hash"
|
file_hash = "file_hash"
|
||||||
message = "Error message"
|
message = "Error message"
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorSelfieWithoutRequest(TestPassportElementErrorSelfieBase):
|
class TestPassportElementErrorSelfieWithoutRequest(PassportElementErrorSelfieTestBase):
|
||||||
def test_slot_behaviour(self, passport_element_error_selfie):
|
def test_slot_behaviour(self, passport_element_error_selfie):
|
||||||
inst = passport_element_error_selfie
|
inst = passport_element_error_selfie
|
||||||
for attr in inst.__slots__:
|
for attr in inst.__slots__:
|
||||||
|
|
|
@ -25,13 +25,13 @@ from tests.auxil.slots import mro_slots
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def passport_element_error_translation_file():
|
def passport_element_error_translation_file():
|
||||||
return PassportElementErrorTranslationFile(
|
return PassportElementErrorTranslationFile(
|
||||||
TestPassportElementErrorTranslationFileBase.type_,
|
PassportElementErrorTranslationFileTestBase.type_,
|
||||||
TestPassportElementErrorTranslationFileBase.file_hash,
|
PassportElementErrorTranslationFileTestBase.file_hash,
|
||||||
TestPassportElementErrorTranslationFileBase.message,
|
PassportElementErrorTranslationFileTestBase.message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorTranslationFileBase:
|
class PassportElementErrorTranslationFileTestBase:
|
||||||
source = "translation_file"
|
source = "translation_file"
|
||||||
type_ = "test_type"
|
type_ = "test_type"
|
||||||
file_hash = "file_hash"
|
file_hash = "file_hash"
|
||||||
|
@ -39,7 +39,7 @@ class TestPassportElementErrorTranslationFileBase:
|
||||||
|
|
||||||
|
|
||||||
class TestPassportElementErrorTranslationFileWithoutRequest(
|
class TestPassportElementErrorTranslationFileWithoutRequest(
|
||||||
TestPassportElementErrorTranslationFileBase
|
PassportElementErrorTranslationFileTestBase
|
||||||
):
|
):
|
||||||
def test_slot_behaviour(self, passport_element_error_translation_file):
|
def test_slot_behaviour(self, passport_element_error_translation_file):
|
||||||
inst = passport_element_error_translation_file
|
inst = passport_element_error_translation_file
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue