mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2025-01-02 09:21:58 +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}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.9]
|
||||
python-version: [3.10]
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
|
|
107
.github/workflows/release_pypi.yml
vendored
107
.github/workflows/release_pypi.yml
vendored
|
@ -1,17 +1,15 @@
|
|||
name: Publish to PyPI
|
||||
|
||||
on:
|
||||
# Run on any tag
|
||||
push:
|
||||
tags:
|
||||
- '**'
|
||||
# manually trigger the workflow - for testing only
|
||||
# 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
|
||||
|
@ -29,11 +27,15 @@ jobs:
|
|||
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-pypi:
|
||||
name: Publish to PyPI
|
||||
# only publish to PyPI on tag pushes
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
needs:
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -52,42 +54,11 @@ jobs:
|
|||
- name: Publish to PyPI
|
||||
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:
|
||||
name: Compute SHA1 Sums and Sign with Sigstore
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- 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:
|
||||
id-token: write # IMPORTANT: mandatory for sigstore
|
||||
|
@ -106,7 +77,7 @@ jobs:
|
|||
sha1sum $file > $file.sha1
|
||||
done
|
||||
- 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:
|
||||
inputs: >-
|
||||
./dist/*.tar.gz
|
||||
|
@ -120,13 +91,8 @@ jobs:
|
|||
github-release:
|
||||
name: Upload to GitHub Release
|
||||
needs:
|
||||
- publish-to-pypi
|
||||
- build
|
||||
- compute-signatures
|
||||
if: |
|
||||
always() && (
|
||||
(needs.publish-to-pypi.result == 'success') &&
|
||||
(needs.compute-signatures.result == 'success')
|
||||
)
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
@ -142,63 +108,22 @@ jobs:
|
|||
- name: Create GitHub Release
|
||||
env:
|
||||
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.
|
||||
run: >-
|
||||
gh release create
|
||||
'${{ github.ref_name }}'
|
||||
'${{ env.TAG }}'
|
||||
--repo '${{ github.repository }}'
|
||||
--generate-notes
|
||||
- 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
|
||||
'${{ github.ref_name }}' 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/**
|
||||
'${{ env.TAG }}' dist/**
|
||||
--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
|
||||
=========
|
||||
|
||||
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
|
||||
============
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
: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
|
||||
: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
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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>`_.
|
||||
|
||||
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.
|
||||
|
||||
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`_.
|
||||
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[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[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``.
|
||||
|
||||
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.reactiontypecustomemoji
|
||||
telegram.reactiontypeemoji
|
||||
telegram.reactiontypepaid
|
||||
telegram.replykeyboardmarkup
|
||||
telegram.replykeyboardremove
|
||||
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.
|
||||
* 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).
|
||||
* 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.
|
||||
* 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.
|
||||
|
|
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_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_*``.
|
||||
|
||||
.. |thumbnail_url_mandatory| replace:: Removal of the deprecated argument ``thumb_url`` made ``thumbnail_url`` mandatory.
|
||||
|
||||
.. |async_context_manager| replace:: Asynchronous context manager which
|
||||
|
||||
.. |reply_parameters| replace:: Description of the message to reply to.
|
||||
|
|
|
@ -67,7 +67,7 @@ all = [
|
|||
]
|
||||
callback-data = [
|
||||
# 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 = [
|
||||
"python-telegram-bot[callback-data,job-queue,rate-limiter,webhooks]",
|
||||
|
|
|
@ -204,6 +204,7 @@ __all__ = (
|
|||
"ReactionType",
|
||||
"ReactionTypeCustomEmoji",
|
||||
"ReactionTypeEmoji",
|
||||
"ReactionTypePaid",
|
||||
"RefundedPayment",
|
||||
"ReplyKeyboardMarkup",
|
||||
"ReplyKeyboardRemove",
|
||||
|
@ -467,7 +468,13 @@ from ._payment.stars import (
|
|||
from ._payment.successfulpayment import SuccessfulPayment
|
||||
from ._poll import InputPollOption, Poll, PollAnswer, PollOption
|
||||
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 ._replykeyboardmarkup import ReplyKeyboardMarkup
|
||||
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
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram Bot."""
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
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
|
||||
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`,
|
||||
:meth:`telegram.ext.Updater.start_webhook`
|
||||
|
||||
|
@ -5019,7 +5008,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
payload (:obj:`str`): Bot-defined invoice payload.
|
||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||
: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
|
||||
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|
||||
|tg_stars|.
|
||||
|
@ -5785,10 +5774,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
|
||||
Args:
|
||||
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
|
||||
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.
|
||||
For timezone naive :obj:`datetime.datetime` objects, the default timezone of the
|
||||
|
@ -5857,10 +5846,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
|
||||
Args:
|
||||
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
|
||||
Now also accepts :obj:`telegram.ChatInviteLink` instances.
|
||||
Now also accepts :class:`telegram.ChatInviteLink` instances.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.ChatInviteLink`
|
||||
|
@ -6156,7 +6145,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
business_connection_id (:obj:`str`, optional): Unique identifier of the business
|
||||
connection on behalf of which the message will be pinned.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
|
||||
Returns:
|
||||
: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
|
||||
connection on behalf of which the message will be unpinned.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
|
||||
Returns:
|
||||
: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
|
||||
|
||||
Args:
|
||||
rights (:obj:`telegram.ChatAdministratorRights`, optional): A
|
||||
:obj:`telegram.ChatAdministratorRights` object describing new default administrator
|
||||
rights (:class:`telegram.ChatAdministratorRights`, optional): A
|
||||
:class:`telegram.ChatAdministratorRights` object describing new default
|
||||
administrator
|
||||
rights. If not specified, the default administrator rights will be cleared.
|
||||
for_channels (:obj:`bool`, optional): Pass :obj:`True` to change the default
|
||||
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.
|
||||
|
||||
Raises:
|
||||
:obj:`telegram.error.TelegramError`
|
||||
:exc:`telegram.error.TelegramError`
|
||||
"""
|
||||
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.
|
||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||
: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
|
||||
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|
||||
|tg_stars|.
|
||||
|
@ -8179,7 +8169,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
) -> bool:
|
||||
"""
|
||||
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,
|
||||
unless it is the creator of the topic.
|
||||
|
||||
|
@ -8447,7 +8437,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
) -> bool:
|
||||
"""
|
||||
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.
|
||||
|
||||
.. 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
|
||||
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
|
||||
|
||||
|
@ -8959,7 +8949,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
: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
|
||||
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:
|
||||
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.
|
||||
name (:obj:`str`): Sticker set name.
|
||||
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
|
||||
set remains unchanged.
|
||||
|
||||
|
@ -9201,6 +9192,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
reply_markup: Optional[ReplyMarkup] = None,
|
||||
business_connection_id: Optional[str] = None,
|
||||
*,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_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,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Message:
|
||||
"""Use this method to send paid media to channel chats.
|
||||
"""Use this method to send paid media.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
|
||||
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
|
||||
to the media.
|
||||
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):
|
||||
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.
|
||||
business_connection_id (:obj:`str`, optional): |business_id_str|
|
||||
|
||||
.. versionadded:: 21.5
|
||||
|
||||
Keyword Args:
|
||||
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,
|
||||
pool_timeout=pool_timeout,
|
||||
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
|
||||
"""See :meth:`telegram.TelegramObject.to_dict`."""
|
||||
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`"""
|
||||
sendPaidMedia = 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,
|
||||
)
|
||||
|
||||
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(
|
||||
self,
|
||||
user_id: int,
|
||||
|
@ -3274,6 +3349,7 @@ class _ChatBase(TelegramObject):
|
|||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
reply_markup: Optional[ReplyMarkup] = None,
|
||||
business_connection_id: Optional[str] = None,
|
||||
*,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
|
@ -3314,6 +3390,7 @@ class _ChatBase(TelegramObject):
|
|||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
business_connection_id=business_connection_id,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ class BackgroundTypeFill(BackgroundType):
|
|||
.. versionadded:: 21.2
|
||||
|
||||
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
|
||||
percentage;
|
||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||
|
@ -315,7 +315,7 @@ class BackgroundTypeFill(BackgroundType):
|
|||
Attributes:
|
||||
type (:obj:`str`): Type of the background. Always
|
||||
: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
|
||||
percentage;
|
||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||
|
@ -349,7 +349,7 @@ class BackgroundTypeWallpaper(BackgroundType):
|
|||
.. versionadded:: 21.2
|
||||
|
||||
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
|
||||
percentage;
|
||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||
|
@ -361,7 +361,7 @@ class BackgroundTypeWallpaper(BackgroundType):
|
|||
Attributes:
|
||||
type (:obj:`str`): Type of the background. Always
|
||||
: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
|
||||
percentage;
|
||||
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
|
||||
|
@ -407,8 +407,8 @@ class BackgroundTypePattern(BackgroundType):
|
|||
.. versionadded:: 21.2
|
||||
|
||||
Args:
|
||||
document (:obj:`telegram.Document`): Document with the pattern.
|
||||
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
|
||||
document (:class:`telegram.Document`): Document with the pattern.
|
||||
fill (:class:`telegram.BackgroundFill`): The background fill that is combined with
|
||||
the pattern.
|
||||
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
|
||||
background;
|
||||
|
@ -422,8 +422,8 @@ class BackgroundTypePattern(BackgroundType):
|
|||
Attributes:
|
||||
type (:obj:`str`): Type of the background. Always
|
||||
:attr:`~telegram.BackgroundType.PATTERN`.
|
||||
document (:obj:`telegram.Document`): Document with the pattern.
|
||||
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
|
||||
document (:class:`telegram.Document`): Document with the pattern.
|
||||
fill (:class:`telegram.BackgroundFill`): The background fill that is combined with
|
||||
the pattern.
|
||||
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
|
||||
background;
|
||||
|
@ -511,10 +511,10 @@ class ChatBackground(TelegramObject):
|
|||
.. versionadded:: 21.2
|
||||
|
||||
Args:
|
||||
type (:obj:`telegram.BackgroundType`): Type of the background.
|
||||
type (:class:`telegram.BackgroundType`): Type of the background.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`telegram.BackgroundType`): Type of the background.
|
||||
type (:class:`telegram.BackgroundType`): Type of the background.
|
||||
"""
|
||||
|
||||
__slots__ = ("type",)
|
||||
|
|
|
@ -78,7 +78,7 @@ class ChatFullInfo(_ChatBase):
|
|||
#collectible-usernames>`_; for private chats, supergroups and channels.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
|
@ -94,8 +94,8 @@ class ChatFullInfo(_ChatBase):
|
|||
chats with business accounts, the opening hours of the business.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of
|
||||
the user.
|
||||
personal_chat (:class:`telegram.Chat`, optional): For private chats, the personal channel
|
||||
of the user.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available
|
||||
|
@ -232,7 +232,7 @@ class ChatFullInfo(_ChatBase):
|
|||
obtained via :meth:`~telegram.Bot.get_chat`.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
|
@ -248,8 +248,8 @@ class ChatFullInfo(_ChatBase):
|
|||
chats with business accounts, the opening hours of the business.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of
|
||||
the user.
|
||||
personal_chat (:class:`telegram.Chat`): Optional. For private chats, the personal channel
|
||||
of the user.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
|
||||
|
|
|
@ -69,6 +69,16 @@ class ChatInviteLink(TelegramObject):
|
|||
created using this link.
|
||||
|
||||
.. 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:
|
||||
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 ``'…'``.
|
||||
|
@ -96,6 +106,15 @@ class ChatInviteLink(TelegramObject):
|
|||
created using this link.
|
||||
|
||||
.. 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",
|
||||
"name",
|
||||
"pending_join_request_count",
|
||||
"subscription_period",
|
||||
"subscription_price",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
|
@ -122,6 +143,8 @@ class ChatInviteLink(TelegramObject):
|
|||
member_limit: Optional[int] = None,
|
||||
name: Optional[str] = None,
|
||||
pending_join_request_count: Optional[int] = None,
|
||||
subscription_period: Optional[int] = None,
|
||||
subscription_price: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
|
@ -140,6 +163,9 @@ class ChatInviteLink(TelegramObject):
|
|||
self.pending_join_request_count: Optional[int] = (
|
||||
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.invite_link,
|
||||
self.creates_join_request,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ChatMember."""
|
||||
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
|
||||
|
||||
|
@ -391,24 +392,34 @@ class ChatMemberMember(ChatMember):
|
|||
|
||||
Args:
|
||||
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:
|
||||
status (:obj:`str`): The member's status in the chat,
|
||||
always :tg-const:`telegram.ChatMember.MEMBER`.
|
||||
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__(
|
||||
self,
|
||||
user: User,
|
||||
until_date: Optional[datetime.datetime] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
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):
|
||||
|
|
|
@ -78,7 +78,7 @@ class InputFile:
|
|||
# here the file handle is already closed and the upload will fail
|
||||
await bot.send_document(chat_id, input_file)
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
|
||||
|
||||
Attributes:
|
||||
|
@ -126,7 +126,7 @@ class InputFile:
|
|||
def field_tuple(self) -> FieldTuple:
|
||||
"""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.
|
||||
|
||||
Returns:
|
||||
|
|
|
@ -49,7 +49,7 @@ class InputSticker(TelegramObject):
|
|||
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
|
||||
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
|
||||
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.
|
||||
keywords (Sequence[:obj:`str`], optional): Sequence of
|
||||
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.MAX_STICKER_EMOJI` emoji associated with the
|
||||
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.
|
||||
keywords (Tuple[:obj:`str`]): Optional. Tuple of
|
||||
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
|
||||
|
|
|
@ -126,7 +126,7 @@ class Giveaway(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["Giveaway"]:
|
||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if data is None:
|
||||
|
@ -262,7 +262,7 @@ class GiveawayWinners(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["GiveawayWinners"]:
|
||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if data is None:
|
||||
|
@ -330,7 +330,7 @@ class GiveawayCompleted(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["GiveawayCompleted"]:
|
||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if data is None:
|
||||
|
|
|
@ -99,7 +99,7 @@ class InlineKeyboardButton(TelegramObject):
|
|||
|
||||
.. 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
|
||||
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
|
||||
|
@ -107,16 +107,14 @@ class InlineKeyboardButton(TelegramObject):
|
|||
a Telegram Business account.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
switch_inline_query (: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 field. May be
|
||||
empty, in which case only the bot's username will be inserted.
|
||||
|
||||
This offers a quick way for the user to open your bot in inline mode in the same chat -
|
||||
good for selecting something from multiple options. Not supported in channels and for
|
||||
messages sent on behalf of a Telegram Business account.
|
||||
switch_inline_query (:obj:`str`, optional): If set, pressing the button will prompt the
|
||||
user to select one of their chats, open that chat and insert the bot's username and the
|
||||
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
|
||||
Business account.
|
||||
|
||||
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.
|
||||
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
|
||||
|
@ -137,7 +135,7 @@ class InlineKeyboardButton(TelegramObject):
|
|||
Note:
|
||||
This type of button **must** always be the first button in the first row and can
|
||||
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
|
||||
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
|
||||
|
@ -170,7 +168,7 @@ class InlineKeyboardButton(TelegramObject):
|
|||
to the bot when the button is pressed, UTF-8
|
||||
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
|
||||
: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
|
||||
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
|
||||
|
@ -178,16 +176,14 @@ class InlineKeyboardButton(TelegramObject):
|
|||
a Telegram Business account.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
switch_inline_query (: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 field. May be
|
||||
empty, in which case only the bot's username will be inserted.
|
||||
|
||||
This offers a quick way for the user to open your bot in inline mode in the same chat -
|
||||
good for selecting something from multiple options. Not supported in channels and for
|
||||
messages sent on behalf of a Telegram Business account.
|
||||
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will prompt the
|
||||
user to select one of their chats, open that chat and insert the bot's username and the
|
||||
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
|
||||
Business account.
|
||||
|
||||
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.
|
||||
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
|
||||
|
@ -208,7 +204,7 @@ class InlineKeyboardButton(TelegramObject):
|
|||
Note:
|
||||
This type of button **must** always be the first button in the first row and can
|
||||
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
|
||||
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
|
||||
|
|
|
@ -50,16 +50,14 @@ class InlineQueryResultGif(InlineQueryResult):
|
|||
gif_width (:obj:`int`, optional): Width of the GIF.
|
||||
gif_height (:obj:`int`, optional): Height of the GIF.
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
..versionchanged:: 20.5
|
||||
|thumbnail_url_mandatory|
|
||||
|
||||
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'``.
|
||||
|
||||
|
@ -82,10 +80,6 @@ class InlineQueryResultGif(InlineQueryResult):
|
|||
|
||||
.. 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:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.GIF`.
|
||||
id (:obj:`str`): Unique identifier for this result,
|
||||
|
|
|
@ -51,16 +51,14 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
|||
mpeg4_width (:obj:`int`, optional): Video width.
|
||||
mpeg4_height (:obj:`int`, optional): Video height.
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
..versionchanged:: 20.5
|
||||
|thumbnail_url_mandatory|
|
||||
|
||||
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'``.
|
||||
|
||||
|
@ -83,9 +81,6 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
|
|||
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
|
||||
|
||||
.. 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:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.MPEG4GIF`.
|
||||
|
|
|
@ -48,15 +48,13 @@ class InlineQueryResultPhoto(InlineQueryResult):
|
|||
: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
|
||||
must not exceed 5MB.
|
||||
thumbnail_url (:obj:`str`, optional): 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.
|
||||
thumbnail_url (:obj:`str`): URL of the thumbnail for the photo.
|
||||
|
||||
.. versionadded:: 20.2
|
||||
|
||||
..versionchanged:: 20.5
|
||||
|thumbnail_url_mandatory|
|
||||
|
||||
photo_width (:obj:`int`, optional): Width of the photo.
|
||||
photo_height (:obj:`int`, optional): Height of the photo.
|
||||
title (:obj:`str`, optional): Title for the result.
|
||||
|
@ -78,10 +76,6 @@ class InlineQueryResultPhoto(InlineQueryResult):
|
|||
|
||||
.. 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:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.PHOTO`.
|
||||
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".
|
||||
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
|
||||
title (:obj:`str`, optional): Title for the result.
|
||||
|
||||
Warning:
|
||||
The Bot API does **not** define this as an optional argument. It is formally
|
||||
optional to ensure backwards compatibility of :paramref:`thumbnail_url` with the
|
||||
deprecated :paramref:`thumb_url`, which required that :paramref:`thumbnail_url`
|
||||
become optional. :class:`TypeError` will be raised if no ``title`` is passed.
|
||||
..versionchanged:: 20.5
|
||||
|thumbnail_url_mandatory|
|
||||
|
||||
title (:obj:`str`): Title for the result.
|
||||
caption (:obj:`str`, optional): Caption of the video to be sent,
|
||||
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
|
||||
parsing.
|
||||
|
@ -92,11 +84,6 @@ class InlineQueryResultVideo(InlineQueryResult):
|
|||
|
||||
.. 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:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.VIDEO`.
|
||||
id (:obj:`str`): Unique identifier for this result,
|
||||
|
|
|
@ -47,7 +47,7 @@ class InputInvoiceMessageContent(InputMessageContent):
|
|||
payload (:obj:`str`): Bot-defined invoice payload.
|
||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||
: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
|
||||
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in
|
||||
|tg_stars|.
|
||||
|
@ -115,7 +115,7 @@ class InputInvoiceMessageContent(InputMessageContent):
|
|||
payload (:obj:`str`): Bot-defined invoice payload.
|
||||
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
|
||||
: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
|
||||
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in `Telegram
|
||||
Stars <https://t.me/BotNews/90>`_.
|
||||
|
|
|
@ -280,15 +280,14 @@ class Message(MaybeInaccessibleMessage):
|
|||
|
||||
Args:
|
||||
message_id (:obj:`int`): Unique message identifier inside this chat.
|
||||
from_user (:class:`telegram.User`, optional): Sender of the message; empty for messages
|
||||
sent to channels. For backward compatibility, this will contain a fake sender user in
|
||||
non-channel chats, if the message was sent on behalf of a chat.
|
||||
sender_chat (:class:`telegram.Chat`, optional): Sender of the message, sent on behalf of a
|
||||
chat. For example, the channel itself for channel posts, the supergroup itself for
|
||||
messages from anonymous group administrators, the linked channel for messages
|
||||
automatically forwarded to the discussion group. For backward compatibility,
|
||||
:attr:`from_user` contains a fake sender user in non-channel chats, if the message was
|
||||
sent on behalf of a chat.
|
||||
from_user (:class:`telegram.User`, optional): Sender of the message; may be empty for
|
||||
messages sent to channels. For backward compatibility, if the message was sent on
|
||||
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 when sent on behalf
|
||||
of a chat. For example, the supergroup itself for messages sent by its anonymous
|
||||
administrators or a linked channel for messages automatically forwarded to the
|
||||
channel's discussion group. For backward compatibility, if the message was sent on
|
||||
behalf of a chat, the field from contains a fake sender user in non-channel chats.
|
||||
date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
|
||||
:class:`datetime.datetime`.
|
||||
|
||||
|
@ -570,36 +569,35 @@ class Message(MaybeInaccessibleMessage):
|
|||
|
||||
.. 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
|
||||
on behalf of the connected business account.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
refunded_payment (:obj:`telegram.RefundedPayment`, optional): Message is a service message
|
||||
about a refunded payment, information about the payment.
|
||||
refunded_payment (:class:`telegram.RefundedPayment`, optional): Message is a service
|
||||
message about a refunded payment, information about the payment.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
|
||||
Attributes:
|
||||
message_id (:obj:`int`): Unique message identifier inside this chat.
|
||||
from_user (:class:`telegram.User`): Optional. Sender of the message; empty for messages
|
||||
sent to channels. For backward compatibility, this will contain a fake sender user in
|
||||
non-channel chats, if the message was sent on behalf of a chat.
|
||||
sender_chat (:class:`telegram.Chat`): Optional. Sender of the message, sent on behalf of a
|
||||
chat. For example, the channel itself for channel posts, the supergroup itself for
|
||||
messages from anonymous group administrators, the linked channel for messages
|
||||
automatically forwarded to the discussion group. For backward compatibility,
|
||||
:attr:`from_user` contains a fake sender user in non-channel chats, if the message was
|
||||
sent on behalf of a chat.
|
||||
from_user (:class:`telegram.User`): Optional. Sender of the message; may be empty for
|
||||
messages sent to channels. For backward compatibility, if the message was sent on
|
||||
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 when sent on behalf
|
||||
of a chat. For example, the supergroup itself for messages sent by its anonymous
|
||||
administrators or a linked channel for messages automatically forwarded to the
|
||||
channel's discussion group. For backward compatibility, if the message was sent on
|
||||
behalf of a chat, the field from contains a fake sender user in non-channel chats.
|
||||
date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
|
||||
:class:`datetime.datetime`.
|
||||
|
||||
|
@ -897,22 +895,22 @@ class Message(MaybeInaccessibleMessage):
|
|||
|
||||
.. 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
|
||||
on behalf of the connected business account.
|
||||
|
||||
.. 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
|
||||
|
||||
.. 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.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
refunded_payment (:obj:`telegram.RefundedPayment`): Optional. Message is a service message
|
||||
about a refunded payment, information about the payment.
|
||||
refunded_payment (:class:`telegram.RefundedPayment`): Optional. Message is a service
|
||||
message about a refunded payment, information about the payment.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
|
||||
|
@ -4114,7 +4112,7 @@ class Message(MaybeInaccessibleMessage):
|
|||
|
||||
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
|
||||
: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`.
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
.. versionchanged:: 21.5
|
||||
Now also passes :attr:`business_connection_id` to
|
||||
:meth:`telegram.Bot.pin_chat_message`.
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
import copy
|
||||
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._telegramobject import TelegramObject
|
||||
|
@ -32,6 +32,8 @@ from telegram._utils.types import JSONDict
|
|||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
|
||||
_SEM = Sequence["MessageEntity"]
|
||||
|
||||
|
||||
class MessageEntity(TelegramObject):
|
||||
"""
|
||||
|
@ -146,9 +148,7 @@ class MessageEntity(TelegramObject):
|
|||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
@staticmethod
|
||||
def adjust_message_entities_to_utf_16(
|
||||
text: str, entities: Sequence["MessageEntity"]
|
||||
) -> Sequence["MessageEntity"]:
|
||||
def adjust_message_entities_to_utf_16(text: str, entities: _SEM) -> _SEM:
|
||||
"""Utility functionality for converting the offset and length of entities from
|
||||
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]
|
||||
accumulated_length += len(text_slice.encode(TextEncoding.UTF_16_LE)) // 2
|
||||
position_translation[position] = accumulated_length
|
||||
# get the final output entites
|
||||
# get the final output entities
|
||||
out = []
|
||||
for entity in entities:
|
||||
translated_positions = position_translation[entity.offset]
|
||||
|
@ -220,6 +220,143 @@ class MessageEntity(TelegramObject):
|
|||
out.append(new_entity)
|
||||
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)
|
||||
"""List[:obj:`str`]: A list of all available message entity types."""
|
||||
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
|
||||
|
|
|
@ -112,7 +112,7 @@ class EncryptedCredentials(TelegramObject):
|
|||
|
||||
Note:
|
||||
This object is decrypted only when originating from
|
||||
:obj:`telegram.PassportData.decrypted_credentials`.
|
||||
:attr:`telegram.PassportData.decrypted_credentials`.
|
||||
|
||||
Args:
|
||||
data (:class:`telegram.Credentials` | :obj:`str`): Decrypted data with unique user's
|
||||
|
|
|
@ -42,7 +42,7 @@ class EncryptedPassportElement(TelegramObject):
|
|||
|
||||
Note:
|
||||
This object is decrypted only when originating from
|
||||
:obj:`telegram.PassportData.decrypted_data`.
|
||||
:attr:`telegram.PassportData.decrypted_data`.
|
||||
|
||||
Args:
|
||||
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
|
||||
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`.
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ from datetime import datetime
|
|||
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
|
||||
|
||||
from telegram import constants
|
||||
from telegram._paidmedia import PaidMedia
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._user import User
|
||||
from telegram._utils import enum
|
||||
|
@ -74,6 +75,17 @@ class RevenueWithdrawalState(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> 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)
|
||||
|
||||
if not data:
|
||||
|
@ -150,6 +162,7 @@ class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["RevenueWithdrawalStateSucceeded"]:
|
||||
"""See :meth:`telegram.RevenueWithdrawalState.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if not data:
|
||||
|
@ -260,13 +273,13 @@ class TransactionPartnerFragment(TransactionPartner):
|
|||
.. versionadded:: 21.4
|
||||
|
||||
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.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): The type of the transaction partner,
|
||||
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.
|
||||
"""
|
||||
|
||||
|
@ -287,6 +300,7 @@ class TransactionPartnerFragment(TransactionPartner):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["TransactionPartnerFragment"]:
|
||||
"""See :meth:`telegram.TransactionPartner.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if not data:
|
||||
|
@ -310,20 +324,33 @@ class TransactionPartnerUser(TransactionPartner):
|
|||
Args:
|
||||
user (:class:`telegram.User`): Information about the user.
|
||||
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:
|
||||
type (:obj:`str`): The type of the transaction partner,
|
||||
always :tg-const:`telegram.TransactionPartner.USER`.
|
||||
user (:class:`telegram.User`): Information about the user.
|
||||
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__(
|
||||
self,
|
||||
user: "User",
|
||||
invoice_payload: Optional[str] = None,
|
||||
paid_media: Optional[Sequence[PaidMedia]] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> None:
|
||||
|
@ -332,6 +359,7 @@ class TransactionPartnerUser(TransactionPartner):
|
|||
with self._unfrozen():
|
||||
self.user: User = user
|
||||
self.invoice_payload: Optional[str] = invoice_payload
|
||||
self.paid_media: Optional[Tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media)
|
||||
self._id_attrs = (
|
||||
self.type,
|
||||
self.user,
|
||||
|
@ -341,12 +369,14 @@ class TransactionPartnerUser(TransactionPartner):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["TransactionPartnerUser"]:
|
||||
"""See :meth:`telegram.TransactionPartner.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
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]
|
||||
|
||||
|
@ -452,6 +482,7 @@ class StarTransaction(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["StarTransaction"]:
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if not data:
|
||||
|
@ -498,6 +529,7 @@ class StarTransactions(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["StarTransactions"]:
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if data is None:
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains 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._telegramobject import TelegramObject
|
||||
|
@ -30,16 +31,22 @@ if TYPE_CHECKING:
|
|||
|
||||
class ReactionType(TelegramObject):
|
||||
"""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
|
||||
.. versionchanged:: 21.5
|
||||
|
||||
Added paid reaction.
|
||||
|
||||
Args:
|
||||
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:
|
||||
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`"""
|
||||
CUSTOM_EMOJI: Final[constants.ReactionType] = 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__(
|
||||
self,
|
||||
type: Union[ # pylint: disable=redefined-builtin
|
||||
Literal["emoji", "custom_emoji"], constants.ReactionType
|
||||
Literal["emoji", "custom_emoji", "paid"], constants.ReactionType
|
||||
],
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
|
@ -71,14 +83,20 @@ class ReactionType(TelegramObject):
|
|||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if not data:
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
if cls is ReactionType and data.get("type") in [cls.EMOJI, cls.CUSTOM_EMOJI]:
|
||||
reaction_type = data.pop("type")
|
||||
if reaction_type == cls.EMOJI:
|
||||
return ReactionTypeEmoji.de_json(data=data, bot=bot)
|
||||
return ReactionTypeCustomEmoji.de_json(data=data, bot=bot)
|
||||
if not data and cls is ReactionType:
|
||||
return None
|
||||
|
||||
_class_mapping: Dict[str, Type[ReactionType]] = {
|
||||
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)
|
||||
|
||||
|
@ -152,6 +170,24 @@ class ReactionTypeCustomEmoji(ReactionType):
|
|||
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):
|
||||
"""This class represents a reaction added to a message along with the number of times it was
|
||||
added.
|
||||
|
|
|
@ -250,7 +250,7 @@ class ExternalReplyInfo(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["ExternalReplyInfo"]:
|
||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if data is None:
|
||||
|
@ -299,7 +299,8 @@ class TextQuote(TelegramObject):
|
|||
message.
|
||||
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
|
||||
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
|
||||
custom_emoji entities are kept in quotes.
|
||||
is_manual (:obj:`bool`, optional): :obj:`True`, if the quote was chosen manually by the
|
||||
|
@ -310,7 +311,7 @@ class TextQuote(TelegramObject):
|
|||
message.
|
||||
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
|
||||
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
|
||||
custom_emoji entities are kept in quotes.
|
||||
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(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["TextQuote"]:
|
||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
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
|
||||
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
|
||||
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
|
||||
:paramref:`quote_parse_mode`.
|
||||
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
|
||||
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
|
||||
more details.
|
||||
quote_entities (Tuple[:obj:`telegram.MessageEntity`]): Optional. A JSON-serialized list of
|
||||
special entities that appear in the quote. It can be specified instead of
|
||||
quote_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. A JSON-serialized list
|
||||
of special entities that appear in the quote. It can be specified instead of
|
||||
:paramref:`quote_parse_mode`.
|
||||
quote_position (:obj:`int`): Optional. Position of the quote in the original message in
|
||||
UTF-16 code units.
|
||||
|
@ -458,7 +460,7 @@ class ReplyParameters(TelegramObject):
|
|||
def de_json(
|
||||
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
|
||||
) -> Optional["ReplyParameters"]:
|
||||
"""See :obj:`telegram.TelegramObject.de_json`."""
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if data is None:
|
||||
|
|
|
@ -354,7 +354,7 @@ class TelegramObject:
|
|||
memodict (:obj:`dict`): A dictionary that maps objects to their copies.
|
||||
|
||||
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
|
||||
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.
|
||||
Returned only in :meth:`telegram.Bot.get_me`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
|
||||
Attributes:
|
||||
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.
|
||||
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`
|
||||
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):
|
||||
"""This enum contains encoding schemes for text.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
|
|
@ -51,6 +51,6 @@ class Version(NamedTuple):
|
|||
|
||||
|
||||
__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__)
|
||||
|
|
|
@ -54,6 +54,7 @@ __all__ = [
|
|||
"ChatLimit",
|
||||
"ChatMemberStatus",
|
||||
"ChatPhotoSize",
|
||||
"ChatSubscriptionLimit",
|
||||
"ChatType",
|
||||
"ContactLimit",
|
||||
"CustomEmojiStickerLimit",
|
||||
|
@ -151,7 +152,7 @@ class _AccentColor(NamedTuple):
|
|||
#: :data:`telegram.__bot_api_version_info__`.
|
||||
#:
|
||||
#: .. 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
|
||||
#: version supported by this version of `python-telegram-bot`. Also available as
|
||||
#: :data:`telegram.__bot_api_version__`.
|
||||
|
@ -2903,6 +2904,11 @@ class ReactionType(StringEnum):
|
|||
""":obj:`str`: A :class:`telegram.ReactionType` with a normal emoji."""
|
||||
CUSTOM_EMOJI = "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):
|
||||
|
@ -3096,3 +3102,22 @@ class BackgroundFillType(StringEnum):
|
|||
""":obj:`str`: A :class:`telegram.BackgroundFill` with gradient fill."""
|
||||
FREEFORM_GRADIENT = "freeform_gradient"
|
||||
""":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,
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
reply_markup: Optional[ReplyMarkup] = None,
|
||||
business_connection_id: Optional[str] = None,
|
||||
*,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
|
@ -4263,6 +4264,57 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
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
|
||||
|
@ -4388,4 +4440,6 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
replaceStickerInSet = replace_sticker_in_set
|
||||
refundStarPayment = refund_star_payment
|
||||
getStarTransactions = get_star_transactions
|
||||
createChatSubscriptionInviteLink = create_chat_subscription_invite_link
|
||||
editChatSubscriptionInviteLink = edit_chat_subscription_invite_link
|
||||
sendPaidMedia = send_paid_media
|
||||
|
|
|
@ -58,7 +58,7 @@ class CallbackQueryHandler(BaseHandler[Update, CCT]):
|
|||
`~telegram.CallbackQuery.game_short_name` or :attr:`~telegram.CallbackQuery.data`
|
||||
matching the defined pattern will be handled
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
|
||||
Warning:
|
||||
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
|
||||
handled by this handler.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
.. versionadded:: 21.5
|
||||
block (:obj:`bool`, optional): Determines whether the return value of the callback should
|
||||
be awaited before processing the next handler in
|
||||
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
|
||||
|
|
|
@ -763,7 +763,6 @@ class Updater(AsyncContextManager["Updater"]):
|
|||
_LOGGER.exception("Invalid token; aborting")
|
||||
raise
|
||||
except TelegramError as telegram_exc:
|
||||
_LOGGER.exception("Error while %s:", description)
|
||||
on_err_cb(telegram_exc)
|
||||
|
||||
# increase waiting times on subsequent errors up to 30secs
|
||||
|
|
|
@ -302,7 +302,7 @@ class BaseFilter:
|
|||
|
||||
class MessageFilter(BaseFilter):
|
||||
"""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.
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ class RequestData:
|
|||
def multipart_data(self) -> UploadFileDict:
|
||||
"""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.
|
||||
"""
|
||||
multipart_data: UploadFileDict = {}
|
||||
|
|
|
@ -79,7 +79,7 @@ class RequestParameter:
|
|||
def multipart_data(self) -> Optional[UploadFileDict]:
|
||||
"""A dict with the file data to upload, if any.
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
.. versionchanged:: 21.5
|
||||
Content may now be a file handle.
|
||||
"""
|
||||
if not self.input_files:
|
||||
|
|
|
@ -51,7 +51,7 @@ async def animation(bot, chat_id):
|
|||
).animation
|
||||
|
||||
|
||||
class TestAnimationBase:
|
||||
class AnimationTestBase:
|
||||
animation_file_id = "CgADAQADngIAAuyVeEez0xRovKi9VAI"
|
||||
animation_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
width = 320
|
||||
|
@ -66,7 +66,7 @@ class TestAnimationBase:
|
|||
caption = "Test *animation*"
|
||||
|
||||
|
||||
class TestAnimationWithoutRequest(TestAnimationBase):
|
||||
class TestAnimationWithoutRequest(AnimationTestBase):
|
||||
def test_slot_behaviour(self, animation):
|
||||
for attr in animation.__slots__:
|
||||
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):
|
||||
message = await bot.send_animation(
|
||||
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
|
||||
|
||||
|
||||
class TestAudioBase:
|
||||
class AudioTestBase:
|
||||
caption = "Test *audio*"
|
||||
performer = "Leandro Toledo"
|
||||
title = "Teste"
|
||||
|
@ -67,7 +67,7 @@ class TestAudioBase:
|
|||
audio_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
|
||||
|
||||
class TestAudioWithoutRequest(TestAudioBase):
|
||||
class TestAudioWithoutRequest(AudioTestBase):
|
||||
def test_slot_behaviour(self, audio):
|
||||
for attr in audio.__slots__:
|
||||
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))
|
||||
|
||||
|
||||
class TestAudioWithRequest(TestAudioBase):
|
||||
class TestAudioWithRequest(AudioTestBase):
|
||||
async def test_send_all_args(self, bot, chat_id, audio_file, thumb_file):
|
||||
message = await bot.send_audio(
|
||||
chat_id,
|
||||
|
|
|
@ -52,7 +52,7 @@ async def chat_photo(bot, super_group_id):
|
|||
)
|
||||
|
||||
|
||||
class TestChatPhotoBase:
|
||||
class ChatPhotoTestBase:
|
||||
chatphoto_small_file_id = "smallCgADAQADngIAAuyVeEez0xRovKi9VAI"
|
||||
chatphoto_big_file_id = "bigCgADAQADngIAAuyVeEez0xRovKi9VAI"
|
||||
chatphoto_small_file_unique_id = "smalladc3145fd2e84d95b64d68eaa22aa33e"
|
||||
|
@ -60,7 +60,7 @@ class TestChatPhotoBase:
|
|||
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):
|
||||
for attr in chat_photo.__slots__:
|
||||
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")
|
||||
def contact():
|
||||
return Contact(
|
||||
TestContactBase.phone_number,
|
||||
TestContactBase.first_name,
|
||||
TestContactBase.last_name,
|
||||
TestContactBase.user_id,
|
||||
ContactTestBase.phone_number,
|
||||
ContactTestBase.first_name,
|
||||
ContactTestBase.last_name,
|
||||
ContactTestBase.user_id,
|
||||
)
|
||||
|
||||
|
||||
class TestContactBase:
|
||||
class ContactTestBase:
|
||||
phone_number = "+11234567890"
|
||||
first_name = "Leandro"
|
||||
last_name = "Toledo"
|
||||
user_id = 23
|
||||
|
||||
|
||||
class TestContactWithoutRequest(TestContactBase):
|
||||
class TestContactWithoutRequest(ContactTestBase):
|
||||
def test_slot_behaviour(self, contact):
|
||||
for attr in contact.__slots__:
|
||||
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(
|
||||
("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
|
||||
|
||||
|
||||
class TestDocumentBase:
|
||||
class DocumentTestBase:
|
||||
caption = "DocumentTest - *Caption*"
|
||||
document_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.gif"
|
||||
file_size = 12948
|
||||
|
@ -62,7 +62,7 @@ class TestDocumentBase:
|
|||
document_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
|
||||
|
||||
class TestDocumentWithoutRequest(TestDocumentBase):
|
||||
class TestDocumentWithoutRequest(DocumentTestBase):
|
||||
def test_slot_behaviour(self, document):
|
||||
for attr in document.__slots__:
|
||||
assert getattr(document, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
|
@ -218,7 +218,7 @@ class TestDocumentWithoutRequest(TestDocumentBase):
|
|||
assert await document.get_file()
|
||||
|
||||
|
||||
class TestDocumentWithRequest(TestDocumentBase):
|
||||
class TestDocumentWithRequest(DocumentTestBase):
|
||||
async def test_error_send_empty_file(self, bot, chat_id):
|
||||
with Path(os.devnull).open("rb") as f, pytest.raises(TelegramError):
|
||||
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")
|
||||
def file(bot):
|
||||
file = File(
|
||||
TestFileBase.file_id,
|
||||
TestFileBase.file_unique_id,
|
||||
file_path=TestFileBase.file_path,
|
||||
file_size=TestFileBase.file_size,
|
||||
FileTestBase.file_id,
|
||||
FileTestBase.file_unique_id,
|
||||
file_path=FileTestBase.file_path,
|
||||
file_size=FileTestBase.file_size,
|
||||
)
|
||||
file.set_bot(bot)
|
||||
file._unfreeze()
|
||||
|
@ -51,10 +51,10 @@ def encrypted_file(bot):
|
|||
"Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
|
||||
)
|
||||
ef = File(
|
||||
TestFileBase.file_id,
|
||||
TestFileBase.file_unique_id,
|
||||
TestFileBase.file_size,
|
||||
TestFileBase.file_path,
|
||||
FileTestBase.file_id,
|
||||
FileTestBase.file_unique_id,
|
||||
FileTestBase.file_size,
|
||||
FileTestBase.file_path,
|
||||
)
|
||||
ef.set_bot(bot)
|
||||
ef.set_credentials(fc)
|
||||
|
@ -69,9 +69,9 @@ def encrypted_local_file(bot):
|
|||
"Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
|
||||
)
|
||||
ef = File(
|
||||
TestFileBase.file_id,
|
||||
TestFileBase.file_unique_id,
|
||||
TestFileBase.file_size,
|
||||
FileTestBase.file_id,
|
||||
FileTestBase.file_unique_id,
|
||||
FileTestBase.file_size,
|
||||
file_path=str(data_file("image_encrypted.jpg")),
|
||||
)
|
||||
ef.set_bot(bot)
|
||||
|
@ -82,16 +82,16 @@ def encrypted_local_file(bot):
|
|||
@pytest.fixture(scope="module")
|
||||
def local_file(bot):
|
||||
file = File(
|
||||
TestFileBase.file_id,
|
||||
TestFileBase.file_unique_id,
|
||||
FileTestBase.file_id,
|
||||
FileTestBase.file_unique_id,
|
||||
file_path=str(data_file("local_file.txt")),
|
||||
file_size=TestFileBase.file_size,
|
||||
file_size=FileTestBase.file_size,
|
||||
)
|
||||
file.set_bot(bot)
|
||||
return file
|
||||
|
||||
|
||||
class TestFileBase:
|
||||
class FileTestBase:
|
||||
file_id = "NOTVALIDDOESNOTMATTER"
|
||||
file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
file_path = (
|
||||
|
@ -101,7 +101,7 @@ class TestFileBase:
|
|||
file_content = "Saint-Saëns".encode() # Intentionally contains unicode chars.
|
||||
|
||||
|
||||
class TestFileWithoutRequest(TestFileBase):
|
||||
class TestFileWithoutRequest(FileTestBase):
|
||||
def test_slot_behaviour(self, file):
|
||||
for attr in file.__slots__:
|
||||
assert getattr(file, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
|
@ -273,7 +273,7 @@ class TestFileWithoutRequest(TestFileBase):
|
|||
assert buf2[: len(buf)] == buf
|
||||
|
||||
|
||||
class TestFileWithRequest(TestFileBase):
|
||||
class TestFileWithRequest(FileTestBase):
|
||||
async def test_error_get_empty_file_id(self, bot):
|
||||
with pytest.raises(TelegramError):
|
||||
await bot.get_file(file_id="")
|
||||
|
|
|
@ -68,94 +68,94 @@ from .test_video import video, video_file # noqa: F401
|
|||
@pytest.fixture(scope="module")
|
||||
def input_media_video(class_thumb_file):
|
||||
return InputMediaVideo(
|
||||
media=TestInputMediaVideoBase.media,
|
||||
caption=TestInputMediaVideoBase.caption,
|
||||
width=TestInputMediaVideoBase.width,
|
||||
height=TestInputMediaVideoBase.height,
|
||||
duration=TestInputMediaVideoBase.duration,
|
||||
parse_mode=TestInputMediaVideoBase.parse_mode,
|
||||
caption_entities=TestInputMediaVideoBase.caption_entities,
|
||||
media=InputMediaVideoTestBase.media,
|
||||
caption=InputMediaVideoTestBase.caption,
|
||||
width=InputMediaVideoTestBase.width,
|
||||
height=InputMediaVideoTestBase.height,
|
||||
duration=InputMediaVideoTestBase.duration,
|
||||
parse_mode=InputMediaVideoTestBase.parse_mode,
|
||||
caption_entities=InputMediaVideoTestBase.caption_entities,
|
||||
thumbnail=class_thumb_file,
|
||||
supports_streaming=TestInputMediaVideoBase.supports_streaming,
|
||||
has_spoiler=TestInputMediaVideoBase.has_spoiler,
|
||||
show_caption_above_media=TestInputMediaVideoBase.show_caption_above_media,
|
||||
supports_streaming=InputMediaVideoTestBase.supports_streaming,
|
||||
has_spoiler=InputMediaVideoTestBase.has_spoiler,
|
||||
show_caption_above_media=InputMediaVideoTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def input_media_photo():
|
||||
return InputMediaPhoto(
|
||||
media=TestInputMediaPhotoBase.media,
|
||||
caption=TestInputMediaPhotoBase.caption,
|
||||
parse_mode=TestInputMediaPhotoBase.parse_mode,
|
||||
caption_entities=TestInputMediaPhotoBase.caption_entities,
|
||||
has_spoiler=TestInputMediaPhotoBase.has_spoiler,
|
||||
show_caption_above_media=TestInputMediaPhotoBase.show_caption_above_media,
|
||||
media=InputMediaPhotoTestBase.media,
|
||||
caption=InputMediaPhotoTestBase.caption,
|
||||
parse_mode=InputMediaPhotoTestBase.parse_mode,
|
||||
caption_entities=InputMediaPhotoTestBase.caption_entities,
|
||||
has_spoiler=InputMediaPhotoTestBase.has_spoiler,
|
||||
show_caption_above_media=InputMediaPhotoTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def input_media_animation(class_thumb_file):
|
||||
return InputMediaAnimation(
|
||||
media=TestInputMediaAnimationBase.media,
|
||||
caption=TestInputMediaAnimationBase.caption,
|
||||
parse_mode=TestInputMediaAnimationBase.parse_mode,
|
||||
caption_entities=TestInputMediaAnimationBase.caption_entities,
|
||||
width=TestInputMediaAnimationBase.width,
|
||||
height=TestInputMediaAnimationBase.height,
|
||||
media=InputMediaAnimationTestBase.media,
|
||||
caption=InputMediaAnimationTestBase.caption,
|
||||
parse_mode=InputMediaAnimationTestBase.parse_mode,
|
||||
caption_entities=InputMediaAnimationTestBase.caption_entities,
|
||||
width=InputMediaAnimationTestBase.width,
|
||||
height=InputMediaAnimationTestBase.height,
|
||||
thumbnail=class_thumb_file,
|
||||
duration=TestInputMediaAnimationBase.duration,
|
||||
has_spoiler=TestInputMediaAnimationBase.has_spoiler,
|
||||
show_caption_above_media=TestInputMediaAnimationBase.show_caption_above_media,
|
||||
duration=InputMediaAnimationTestBase.duration,
|
||||
has_spoiler=InputMediaAnimationTestBase.has_spoiler,
|
||||
show_caption_above_media=InputMediaAnimationTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def input_media_audio(class_thumb_file):
|
||||
return InputMediaAudio(
|
||||
media=TestInputMediaAudioBase.media,
|
||||
caption=TestInputMediaAudioBase.caption,
|
||||
duration=TestInputMediaAudioBase.duration,
|
||||
performer=TestInputMediaAudioBase.performer,
|
||||
title=TestInputMediaAudioBase.title,
|
||||
media=InputMediaAudioTestBase.media,
|
||||
caption=InputMediaAudioTestBase.caption,
|
||||
duration=InputMediaAudioTestBase.duration,
|
||||
performer=InputMediaAudioTestBase.performer,
|
||||
title=InputMediaAudioTestBase.title,
|
||||
thumbnail=class_thumb_file,
|
||||
parse_mode=TestInputMediaAudioBase.parse_mode,
|
||||
caption_entities=TestInputMediaAudioBase.caption_entities,
|
||||
parse_mode=InputMediaAudioTestBase.parse_mode,
|
||||
caption_entities=InputMediaAudioTestBase.caption_entities,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def input_media_document(class_thumb_file):
|
||||
return InputMediaDocument(
|
||||
media=TestInputMediaDocumentBase.media,
|
||||
caption=TestInputMediaDocumentBase.caption,
|
||||
media=InputMediaDocumentTestBase.media,
|
||||
caption=InputMediaDocumentTestBase.caption,
|
||||
thumbnail=class_thumb_file,
|
||||
parse_mode=TestInputMediaDocumentBase.parse_mode,
|
||||
caption_entities=TestInputMediaDocumentBase.caption_entities,
|
||||
disable_content_type_detection=TestInputMediaDocumentBase.disable_content_type_detection,
|
||||
parse_mode=InputMediaDocumentTestBase.parse_mode,
|
||||
caption_entities=InputMediaDocumentTestBase.caption_entities,
|
||||
disable_content_type_detection=InputMediaDocumentTestBase.disable_content_type_detection,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def input_paid_media_photo():
|
||||
return InputPaidMediaPhoto(
|
||||
media=TestInputMediaPhotoBase.media,
|
||||
media=InputMediaPhotoTestBase.media,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def input_paid_media_video(class_thumb_file):
|
||||
return InputPaidMediaVideo(
|
||||
media=TestInputMediaVideoBase.media,
|
||||
media=InputMediaVideoTestBase.media,
|
||||
thumbnail=class_thumb_file,
|
||||
width=TestInputMediaVideoBase.width,
|
||||
height=TestInputMediaVideoBase.height,
|
||||
duration=TestInputMediaVideoBase.duration,
|
||||
supports_streaming=TestInputMediaVideoBase.supports_streaming,
|
||||
width=InputMediaVideoTestBase.width,
|
||||
height=InputMediaVideoTestBase.height,
|
||||
duration=InputMediaVideoTestBase.duration,
|
||||
supports_streaming=InputMediaVideoTestBase.supports_streaming,
|
||||
)
|
||||
|
||||
|
||||
class TestInputMediaVideoBase:
|
||||
class InputMediaVideoTestBase:
|
||||
type_ = "video"
|
||||
media = "NOTAREALFILEID"
|
||||
caption = "My Caption"
|
||||
|
@ -169,7 +169,7 @@ class TestInputMediaVideoBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInputMediaVideoWithoutRequest(TestInputMediaVideoBase):
|
||||
class TestInputMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
def test_slot_behaviour(self, input_media_video):
|
||||
inst = input_media_video
|
||||
for attr in inst.__slots__:
|
||||
|
@ -258,7 +258,7 @@ class TestInputMediaVideoWithoutRequest(TestInputMediaVideoBase):
|
|||
)
|
||||
|
||||
|
||||
class TestInputMediaPhotoBase:
|
||||
class InputMediaPhotoTestBase:
|
||||
type_ = "photo"
|
||||
media = "NOTAREALFILEID"
|
||||
caption = "My Caption"
|
||||
|
@ -268,7 +268,7 @@ class TestInputMediaPhotoBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInputMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
||||
class TestInputMediaPhotoWithoutRequest(InputMediaPhotoTestBase):
|
||||
def test_slot_behaviour(self, input_media_photo):
|
||||
inst = input_media_photo
|
||||
for attr in inst.__slots__:
|
||||
|
@ -322,7 +322,7 @@ class TestInputMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
|||
assert input_media_photo.media == data_file("telegram.mp4").as_uri()
|
||||
|
||||
|
||||
class TestInputMediaAnimationBase:
|
||||
class InputMediaAnimationTestBase:
|
||||
type_ = "animation"
|
||||
media = "NOTAREALFILEID"
|
||||
caption = "My Caption"
|
||||
|
@ -335,7 +335,7 @@ class TestInputMediaAnimationBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInputMediaAnimationWithoutRequest(TestInputMediaAnimationBase):
|
||||
class TestInputMediaAnimationWithoutRequest(InputMediaAnimationTestBase):
|
||||
def test_slot_behaviour(self, input_media_animation):
|
||||
inst = input_media_animation
|
||||
for attr in inst.__slots__:
|
||||
|
@ -396,7 +396,7 @@ class TestInputMediaAnimationWithoutRequest(TestInputMediaAnimationBase):
|
|||
assert input_media_animation.thumbnail == data_file("telegram.jpg").as_uri()
|
||||
|
||||
|
||||
class TestInputMediaAudioBase:
|
||||
class InputMediaAudioTestBase:
|
||||
type_ = "audio"
|
||||
media = "NOTAREALFILEID"
|
||||
caption = "My Caption"
|
||||
|
@ -407,7 +407,7 @@ class TestInputMediaAudioBase:
|
|||
caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
|
||||
|
||||
|
||||
class TestInputMediaAudioWithoutRequest(TestInputMediaAudioBase):
|
||||
class TestInputMediaAudioWithoutRequest(InputMediaAudioTestBase):
|
||||
def test_slot_behaviour(self, input_media_audio):
|
||||
inst = input_media_audio
|
||||
for attr in inst.__slots__:
|
||||
|
@ -467,7 +467,7 @@ class TestInputMediaAudioWithoutRequest(TestInputMediaAudioBase):
|
|||
assert input_media_audio.thumbnail == data_file("telegram.jpg").as_uri()
|
||||
|
||||
|
||||
class TestInputMediaDocumentBase:
|
||||
class InputMediaDocumentTestBase:
|
||||
type_ = "document"
|
||||
media = "NOTAREALFILEID"
|
||||
caption = "My Caption"
|
||||
|
@ -476,7 +476,7 @@ class TestInputMediaDocumentBase:
|
|||
disable_content_type_detection = True
|
||||
|
||||
|
||||
class TestInputMediaDocumentWithoutRequest(TestInputMediaDocumentBase):
|
||||
class TestInputMediaDocumentWithoutRequest(InputMediaDocumentTestBase):
|
||||
def test_slot_behaviour(self, input_media_document):
|
||||
inst = input_media_document
|
||||
for attr in inst.__slots__:
|
||||
|
@ -535,7 +535,7 @@ class TestInputMediaDocumentWithoutRequest(TestInputMediaDocumentBase):
|
|||
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):
|
||||
inst = input_paid_media_photo
|
||||
for attr in inst.__slots__:
|
||||
|
@ -568,7 +568,7 @@ class TestInputPaidMediaPhotoWithoutRequest(TestInputMediaPhotoBase):
|
|||
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):
|
||||
inst = input_paid_media_video
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -29,15 +29,15 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def input_sticker():
|
||||
return InputSticker(
|
||||
sticker=TestInputStickerBase.sticker,
|
||||
emoji_list=TestInputStickerBase.emoji_list,
|
||||
mask_position=TestInputStickerBase.mask_position,
|
||||
keywords=TestInputStickerBase.keywords,
|
||||
format=TestInputStickerBase.format,
|
||||
sticker=InputStickerTestBase.sticker,
|
||||
emoji_list=InputStickerTestBase.emoji_list,
|
||||
mask_position=InputStickerTestBase.mask_position,
|
||||
keywords=InputStickerTestBase.keywords,
|
||||
format=InputStickerTestBase.format,
|
||||
)
|
||||
|
||||
|
||||
class TestInputStickerBase:
|
||||
class InputStickerTestBase:
|
||||
sticker = "fake_file_id"
|
||||
emoji_list = ("👍", "👎")
|
||||
mask_position = MaskPosition("forehead", 0.5, 0.5, 0.5)
|
||||
|
@ -45,7 +45,7 @@ class TestInputStickerBase:
|
|||
format = "static"
|
||||
|
||||
|
||||
class TestInputStickerWithoutRequest(TestInputStickerBase):
|
||||
class TestInputStickerWithoutRequest(InputStickerTestBase):
|
||||
def test_slot_behaviour(self, input_sticker):
|
||||
inst = input_sticker
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -31,16 +31,16 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def location():
|
||||
return Location(
|
||||
latitude=TestLocationBase.latitude,
|
||||
longitude=TestLocationBase.longitude,
|
||||
horizontal_accuracy=TestLocationBase.horizontal_accuracy,
|
||||
live_period=TestLocationBase.live_period,
|
||||
heading=TestLocationBase.live_period,
|
||||
proximity_alert_radius=TestLocationBase.proximity_alert_radius,
|
||||
latitude=LocationTestBase.latitude,
|
||||
longitude=LocationTestBase.longitude,
|
||||
horizontal_accuracy=LocationTestBase.horizontal_accuracy,
|
||||
live_period=LocationTestBase.live_period,
|
||||
heading=LocationTestBase.live_period,
|
||||
proximity_alert_radius=LocationTestBase.proximity_alert_radius,
|
||||
)
|
||||
|
||||
|
||||
class TestLocationBase:
|
||||
class LocationTestBase:
|
||||
latitude = -23.691288
|
||||
longitude = -46.788279
|
||||
horizontal_accuracy = 999
|
||||
|
@ -49,7 +49,7 @@ class TestLocationBase:
|
|||
proximity_alert_radius = 50
|
||||
|
||||
|
||||
class TestLocationWithoutRequest(TestLocationBase):
|
||||
class TestLocationWithoutRequest(LocationTestBase):
|
||||
def test_slot_behaviour(self, location):
|
||||
for attr in location.__slots__:
|
||||
assert getattr(location, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
|
|
|
@ -65,7 +65,7 @@ def photo(photolist):
|
|||
return photolist[-1]
|
||||
|
||||
|
||||
class TestPhotoBase:
|
||||
class PhotoTestBase:
|
||||
width = 800
|
||||
height = 800
|
||||
caption = "<b>PhotoTest</b> - *Caption*"
|
||||
|
@ -75,7 +75,7 @@ class TestPhotoBase:
|
|||
file_size = [29176, 27662]
|
||||
|
||||
|
||||
class TestPhotoWithoutRequest(TestPhotoBase):
|
||||
class TestPhotoWithoutRequest(PhotoTestBase):
|
||||
def test_slot_behaviour(self, photo):
|
||||
for attr in photo.__slots__:
|
||||
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))
|
||||
|
||||
|
||||
class TestPhotoWithRequest(TestPhotoBase):
|
||||
class TestPhotoWithRequest(PhotoTestBase):
|
||||
async def test_send_photo_all_args(self, bot, chat_id, photo_file):
|
||||
message = await bot.send_photo(
|
||||
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
|
||||
# necessary to properly test needs_repainting
|
||||
with sticker._unfrozen():
|
||||
sticker.needs_repainting = TestStickerBase.needs_repainting
|
||||
sticker.needs_repainting = StickerTestBase.needs_repainting
|
||||
return sticker
|
||||
|
||||
|
||||
|
@ -89,7 +89,7 @@ def video_sticker(bot, chat_id):
|
|||
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'
|
||||
# Serving sticker from gh since our server sends wrong content_type
|
||||
sticker_file_url = (
|
||||
|
@ -116,7 +116,7 @@ class TestStickerBase:
|
|||
premium_animation = File("this_is_an_id", "this_is_an_unique_id")
|
||||
|
||||
|
||||
class TestStickerWithoutRequest(TestStickerBase):
|
||||
class TestStickerWithoutRequest(StickerTestBase):
|
||||
def test_slot_behaviour(self, sticker):
|
||||
for attr in sticker.__slots__:
|
||||
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):
|
||||
message = await bot.send_sticker(
|
||||
chat_id, sticker=sticker_file, disable_notification=False, protect_content=True
|
||||
|
@ -572,7 +572,7 @@ def sticker_set_thumb_file():
|
|||
yield file
|
||||
|
||||
|
||||
class TestStickerSetBase:
|
||||
class StickerSetTestBase:
|
||||
title = "Test stickers"
|
||||
stickers = [Sticker("file_id", "file_un_id", 512, 512, True, True, Sticker.REGULAR)]
|
||||
name = "NOTAREALNAME"
|
||||
|
@ -580,7 +580,7 @@ class TestStickerSetBase:
|
|||
contains_masks = True
|
||||
|
||||
|
||||
class TestStickerSetWithoutRequest(TestStickerSetBase):
|
||||
class TestStickerSetWithoutRequest(StickerSetTestBase):
|
||||
def test_slot_behaviour(self):
|
||||
inst = StickerSet("this", "is", self.stickers, "not")
|
||||
for attr in inst.__slots__:
|
||||
|
@ -1064,21 +1064,21 @@ class TestStickerSetWithRequest:
|
|||
@pytest.fixture(scope="module")
|
||||
def mask_position():
|
||||
return MaskPosition(
|
||||
TestMaskPositionBase.point,
|
||||
TestMaskPositionBase.x_shift,
|
||||
TestMaskPositionBase.y_shift,
|
||||
TestMaskPositionBase.scale,
|
||||
MaskPositionTestBase.point,
|
||||
MaskPositionTestBase.x_shift,
|
||||
MaskPositionTestBase.y_shift,
|
||||
MaskPositionTestBase.scale,
|
||||
)
|
||||
|
||||
|
||||
class TestMaskPositionBase:
|
||||
class MaskPositionTestBase:
|
||||
point = MaskPosition.EYES
|
||||
x_shift = -1
|
||||
y_shift = 1
|
||||
scale = 2
|
||||
|
||||
|
||||
class TestMaskPositionWithoutRequest(TestMaskPositionBase):
|
||||
class TestMaskPositionWithoutRequest(MaskPositionTestBase):
|
||||
def test_slot_behaviour(self, mask_position):
|
||||
inst = mask_position
|
||||
for attr in inst.__slots__:
|
||||
|
@ -1130,7 +1130,7 @@ class TestMaskPositionWithoutRequest(TestMaskPositionBase):
|
|||
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):
|
||||
name = f"masks_by_{bot.username}"
|
||||
try:
|
||||
|
|
|
@ -31,17 +31,17 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def venue():
|
||||
return Venue(
|
||||
TestVenueBase.location,
|
||||
TestVenueBase.title,
|
||||
TestVenueBase.address,
|
||||
foursquare_id=TestVenueBase.foursquare_id,
|
||||
foursquare_type=TestVenueBase.foursquare_type,
|
||||
google_place_id=TestVenueBase.google_place_id,
|
||||
google_place_type=TestVenueBase.google_place_type,
|
||||
VenueTestBase.location,
|
||||
VenueTestBase.title,
|
||||
VenueTestBase.address,
|
||||
foursquare_id=VenueTestBase.foursquare_id,
|
||||
foursquare_type=VenueTestBase.foursquare_type,
|
||||
google_place_id=VenueTestBase.google_place_id,
|
||||
google_place_type=VenueTestBase.google_place_type,
|
||||
)
|
||||
|
||||
|
||||
class TestVenueBase:
|
||||
class VenueTestBase:
|
||||
location = Location(longitude=-46.788279, latitude=-23.691288)
|
||||
title = "title"
|
||||
address = "address"
|
||||
|
@ -51,7 +51,7 @@ class TestVenueBase:
|
|||
google_place_type = "google place type"
|
||||
|
||||
|
||||
class TestVenueWithoutRequest(TestVenueBase):
|
||||
class TestVenueWithoutRequest(VenueTestBase):
|
||||
def test_slot_behaviour(self, venue):
|
||||
for attr in venue.__slots__:
|
||||
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(
|
||||
("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
|
||||
|
||||
|
||||
class TestVideoBase:
|
||||
class VideoTestBase:
|
||||
width = 360
|
||||
height = 640
|
||||
duration = 5
|
||||
|
@ -66,7 +66,7 @@ class TestVideoBase:
|
|||
video_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
|
||||
|
||||
class TestVideoWithoutRequest(TestVideoBase):
|
||||
class TestVideoWithoutRequest(VideoTestBase):
|
||||
def test_slot_behaviour(self, video):
|
||||
for attr in video.__slots__:
|
||||
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))
|
||||
|
||||
|
||||
class TestVideoWithRequest(TestVideoBase):
|
||||
class TestVideoWithRequest(VideoTestBase):
|
||||
async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file):
|
||||
message = await bot.send_video(
|
||||
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
|
||||
|
||||
|
||||
class TestVideoNoteBase:
|
||||
class VideoNoteTestBase:
|
||||
length = 240
|
||||
duration = 3
|
||||
file_size = 132084
|
||||
|
@ -60,7 +60,7 @@ class TestVideoNoteBase:
|
|||
videonote_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
|
||||
|
||||
class TestVideoNoteWithoutRequest(TestVideoNoteBase):
|
||||
class TestVideoNoteWithoutRequest(VideoNoteTestBase):
|
||||
def test_slot_behaviour(self, video_note):
|
||||
for attr in video_note.__slots__:
|
||||
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):
|
||||
message = await bot.send_video_note(
|
||||
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
|
||||
|
||||
|
||||
class TestVoiceBase:
|
||||
class VoiceTestBase:
|
||||
duration = 3
|
||||
mime_type = "audio/ogg"
|
||||
file_size = 9199
|
||||
|
@ -59,7 +59,7 @@ class TestVoiceBase:
|
|||
voice_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
|
||||
|
||||
|
||||
class TestVoiceWithoutRequest(TestVoiceBase):
|
||||
class TestVoiceWithoutRequest(VoiceTestBase):
|
||||
def test_slot_behaviour(self, voice):
|
||||
for attr in voice.__slots__:
|
||||
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))
|
||||
|
||||
|
||||
class TestVoiceWithRequest(TestVoiceBase):
|
||||
class TestVoiceWithRequest(VoiceTestBase):
|
||||
async def test_send_all_args(self, bot, chat_id, voice_file, voice):
|
||||
message = await bot.send_voice(
|
||||
chat_id,
|
||||
|
|
|
@ -26,18 +26,18 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def game():
|
||||
game = Game(
|
||||
TestGameBase.title,
|
||||
TestGameBase.description,
|
||||
TestGameBase.photo,
|
||||
text=TestGameBase.text,
|
||||
text_entities=TestGameBase.text_entities,
|
||||
animation=TestGameBase.animation,
|
||||
GameTestBase.title,
|
||||
GameTestBase.description,
|
||||
GameTestBase.photo,
|
||||
text=GameTestBase.text,
|
||||
text_entities=GameTestBase.text_entities,
|
||||
animation=GameTestBase.animation,
|
||||
)
|
||||
game._unfreeze()
|
||||
return game
|
||||
|
||||
|
||||
class TestGameBase:
|
||||
class GameTestBase:
|
||||
title = "Python-telegram-bot Test Game"
|
||||
description = "description"
|
||||
photo = [PhotoSize("Blah", "ElseBlah", 640, 360, file_size=0)]
|
||||
|
@ -49,7 +49,7 @@ class TestGameBase:
|
|||
animation = Animation("blah", "unique_id", 320, 180, 1)
|
||||
|
||||
|
||||
class TestGameWithoutRequest(TestGameBase):
|
||||
class TestGameWithoutRequest(GameTestBase):
|
||||
def test_slot_behaviour(self, game):
|
||||
for attr in game.__slots__:
|
||||
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")
|
||||
def game_highscore():
|
||||
return GameHighScore(
|
||||
TestGameHighScoreBase.position, TestGameHighScoreBase.user, TestGameHighScoreBase.score
|
||||
GameHighScoreTestBase.position, GameHighScoreTestBase.user, GameHighScoreTestBase.score
|
||||
)
|
||||
|
||||
|
||||
class TestGameHighScoreBase:
|
||||
class GameHighScoreTestBase:
|
||||
position = 12
|
||||
user = User(2, "test user", False)
|
||||
score = 42
|
||||
|
||||
|
||||
class TestGameHighScoreWithoutRequest(TestGameHighScoreBase):
|
||||
class TestGameHighScoreWithoutRequest(GameHighScoreTestBase):
|
||||
def test_slot_behaviour(self, game_highscore):
|
||||
for attr in game_highscore.__slots__:
|
||||
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")
|
||||
def inline_keyboard_button():
|
||||
return InlineKeyboardButton(
|
||||
TestInlineKeyboardButtonBase.text,
|
||||
url=TestInlineKeyboardButtonBase.url,
|
||||
callback_data=TestInlineKeyboardButtonBase.callback_data,
|
||||
switch_inline_query=TestInlineKeyboardButtonBase.switch_inline_query,
|
||||
InlineKeyboardButtonTestBase.text,
|
||||
url=InlineKeyboardButtonTestBase.url,
|
||||
callback_data=InlineKeyboardButtonTestBase.callback_data,
|
||||
switch_inline_query=InlineKeyboardButtonTestBase.switch_inline_query,
|
||||
switch_inline_query_current_chat=(
|
||||
TestInlineKeyboardButtonBase.switch_inline_query_current_chat
|
||||
InlineKeyboardButtonTestBase.switch_inline_query_current_chat
|
||||
),
|
||||
callback_game=TestInlineKeyboardButtonBase.callback_game,
|
||||
pay=TestInlineKeyboardButtonBase.pay,
|
||||
login_url=TestInlineKeyboardButtonBase.login_url,
|
||||
web_app=TestInlineKeyboardButtonBase.web_app,
|
||||
callback_game=InlineKeyboardButtonTestBase.callback_game,
|
||||
pay=InlineKeyboardButtonTestBase.pay,
|
||||
login_url=InlineKeyboardButtonTestBase.login_url,
|
||||
web_app=InlineKeyboardButtonTestBase.web_app,
|
||||
switch_inline_query_chosen_chat=(
|
||||
TestInlineKeyboardButtonBase.switch_inline_query_chosen_chat
|
||||
InlineKeyboardButtonTestBase.switch_inline_query_chosen_chat
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class TestInlineKeyboardButtonBase:
|
||||
class InlineKeyboardButtonTestBase:
|
||||
text = "text"
|
||||
url = "url"
|
||||
callback_data = "callback data"
|
||||
|
@ -62,7 +62,7 @@ class TestInlineKeyboardButtonBase:
|
|||
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):
|
||||
inst = inline_keyboard_button
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -31,10 +31,10 @@ from tests.auxil.slots import mro_slots
|
|||
|
||||
@pytest.fixture(scope="module")
|
||||
def inline_keyboard_markup():
|
||||
return InlineKeyboardMarkup(TestInlineKeyboardMarkupBase.inline_keyboard)
|
||||
return InlineKeyboardMarkup(InlineKeyboardMarkupTestBase.inline_keyboard)
|
||||
|
||||
|
||||
class TestInlineKeyboardMarkupBase:
|
||||
class InlineKeyboardMarkupTestBase:
|
||||
inline_keyboard = [
|
||||
[
|
||||
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):
|
||||
inst = inline_keyboard_markup
|
||||
for attr in inst.__slots__:
|
||||
|
@ -228,7 +228,7 @@ class TestInlineKeyboardMarkupWithoutRequest(TestInlineKeyboardMarkupBase):
|
|||
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(
|
||||
self, bot, chat_id, inline_keyboard_markup
|
||||
):
|
||||
|
|
|
@ -31,17 +31,17 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query(bot):
|
||||
ilq = InlineQuery(
|
||||
TestInlineQueryBase.id_,
|
||||
TestInlineQueryBase.from_user,
|
||||
TestInlineQueryBase.query,
|
||||
TestInlineQueryBase.offset,
|
||||
location=TestInlineQueryBase.location,
|
||||
InlineQueryTestBase.id_,
|
||||
InlineQueryTestBase.from_user,
|
||||
InlineQueryTestBase.query,
|
||||
InlineQueryTestBase.offset,
|
||||
location=InlineQueryTestBase.location,
|
||||
)
|
||||
ilq.set_bot(bot)
|
||||
return ilq
|
||||
|
||||
|
||||
class TestInlineQueryBase:
|
||||
class InlineQueryTestBase:
|
||||
id_ = 1234
|
||||
from_user = User(1, "First name", False)
|
||||
query = "query text"
|
||||
|
@ -49,7 +49,7 @@ class TestInlineQueryBase:
|
|||
location = Location(8.8, 53.1)
|
||||
|
||||
|
||||
class TestInlineQueryWithoutRequest(TestInlineQueryBase):
|
||||
class TestInlineQueryWithoutRequest(InlineQueryTestBase):
|
||||
def test_slot_behaviour(self, inline_query):
|
||||
for attr in inline_query.__slots__:
|
||||
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")
|
||||
def inline_query_result_article():
|
||||
return InlineQueryResultArticle(
|
||||
TestInlineQueryResultArticleBase.id_,
|
||||
TestInlineQueryResultArticleBase.title,
|
||||
input_message_content=TestInlineQueryResultArticleBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultArticleBase.reply_markup,
|
||||
url=TestInlineQueryResultArticleBase.url,
|
||||
hide_url=TestInlineQueryResultArticleBase.hide_url,
|
||||
description=TestInlineQueryResultArticleBase.description,
|
||||
thumbnail_url=TestInlineQueryResultArticleBase.thumbnail_url,
|
||||
thumbnail_height=TestInlineQueryResultArticleBase.thumbnail_height,
|
||||
thumbnail_width=TestInlineQueryResultArticleBase.thumbnail_width,
|
||||
InlineQueryResultArticleTestBase.id_,
|
||||
InlineQueryResultArticleTestBase.title,
|
||||
input_message_content=InlineQueryResultArticleTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultArticleTestBase.reply_markup,
|
||||
url=InlineQueryResultArticleTestBase.url,
|
||||
hide_url=InlineQueryResultArticleTestBase.hide_url,
|
||||
description=InlineQueryResultArticleTestBase.description,
|
||||
thumbnail_url=InlineQueryResultArticleTestBase.thumbnail_url,
|
||||
thumbnail_height=InlineQueryResultArticleTestBase.thumbnail_height,
|
||||
thumbnail_width=InlineQueryResultArticleTestBase.thumbnail_width,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultArticleBase:
|
||||
class InlineQueryResultArticleTestBase:
|
||||
id_ = "id"
|
||||
type_ = "article"
|
||||
title = "title"
|
||||
|
@ -61,7 +61,7 @@ class TestInlineQueryResultArticleBase:
|
|||
thumbnail_width = 15
|
||||
|
||||
|
||||
class TestInlineQueryResultArticleWithoutRequest(TestInlineQueryResultArticleBase):
|
||||
class TestInlineQueryResultArticleWithoutRequest(InlineQueryResultArticleTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_article):
|
||||
inst = inline_query_result_article
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -33,20 +33,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_audio():
|
||||
return InlineQueryResultAudio(
|
||||
TestInlineQueryResultAudioBase.id_,
|
||||
TestInlineQueryResultAudioBase.audio_url,
|
||||
TestInlineQueryResultAudioBase.title,
|
||||
performer=TestInlineQueryResultAudioBase.performer,
|
||||
audio_duration=TestInlineQueryResultAudioBase.audio_duration,
|
||||
caption=TestInlineQueryResultAudioBase.caption,
|
||||
parse_mode=TestInlineQueryResultAudioBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultAudioBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultAudioBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultAudioBase.reply_markup,
|
||||
InlineQueryResultAudioTestBase.id_,
|
||||
InlineQueryResultAudioTestBase.audio_url,
|
||||
InlineQueryResultAudioTestBase.title,
|
||||
performer=InlineQueryResultAudioTestBase.performer,
|
||||
audio_duration=InlineQueryResultAudioTestBase.audio_duration,
|
||||
caption=InlineQueryResultAudioTestBase.caption,
|
||||
parse_mode=InlineQueryResultAudioTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultAudioTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultAudioTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultAudioTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultAudioBase:
|
||||
class InlineQueryResultAudioTestBase:
|
||||
id_ = "id"
|
||||
type_ = "audio"
|
||||
audio_url = "audio url"
|
||||
|
@ -60,7 +60,7 @@ class TestInlineQueryResultAudioBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultAudioWithoutRequest(TestInlineQueryResultAudioBase):
|
||||
class TestInlineQueryResultAudioWithoutRequest(InlineQueryResultAudioTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_audio):
|
||||
inst = inline_query_result_audio
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -33,17 +33,17 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_audio():
|
||||
return InlineQueryResultCachedAudio(
|
||||
TestInlineQueryResultCachedAudioBase.id_,
|
||||
TestInlineQueryResultCachedAudioBase.audio_file_id,
|
||||
caption=TestInlineQueryResultCachedAudioBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedAudioBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedAudioBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultCachedAudioBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedAudioBase.reply_markup,
|
||||
InlineQueryResultCachedAudioTestBase.id_,
|
||||
InlineQueryResultCachedAudioTestBase.audio_file_id,
|
||||
caption=InlineQueryResultCachedAudioTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedAudioTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedAudioTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultCachedAudioTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedAudioTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedAudioBase:
|
||||
class InlineQueryResultCachedAudioTestBase:
|
||||
id_ = "id"
|
||||
type_ = "audio"
|
||||
audio_file_id = "audio file id"
|
||||
|
@ -54,7 +54,7 @@ class TestInlineQueryResultCachedAudioBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedAudioWithoutRequest(TestInlineQueryResultCachedAudioBase):
|
||||
class TestInlineQueryResultCachedAudioWithoutRequest(InlineQueryResultCachedAudioTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_audio):
|
||||
inst = inline_query_result_cached_audio
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -33,19 +33,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_document():
|
||||
return InlineQueryResultCachedDocument(
|
||||
TestInlineQueryResultCachedDocumentBase.id_,
|
||||
TestInlineQueryResultCachedDocumentBase.title,
|
||||
TestInlineQueryResultCachedDocumentBase.document_file_id,
|
||||
caption=TestInlineQueryResultCachedDocumentBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedDocumentBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedDocumentBase.caption_entities,
|
||||
description=TestInlineQueryResultCachedDocumentBase.description,
|
||||
input_message_content=TestInlineQueryResultCachedDocumentBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedDocumentBase.reply_markup,
|
||||
InlineQueryResultCachedDocumentTestBase.id_,
|
||||
InlineQueryResultCachedDocumentTestBase.title,
|
||||
InlineQueryResultCachedDocumentTestBase.document_file_id,
|
||||
caption=InlineQueryResultCachedDocumentTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedDocumentTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedDocumentTestBase.caption_entities,
|
||||
description=InlineQueryResultCachedDocumentTestBase.description,
|
||||
input_message_content=InlineQueryResultCachedDocumentTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedDocumentTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedDocumentBase:
|
||||
class InlineQueryResultCachedDocumentTestBase:
|
||||
id_ = "id"
|
||||
type_ = "document"
|
||||
document_file_id = "document file id"
|
||||
|
@ -58,7 +58,7 @@ class TestInlineQueryResultCachedDocumentBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedDocumentWithoutRequest(TestInlineQueryResultCachedDocumentBase):
|
||||
class TestInlineQueryResultCachedDocumentWithoutRequest(InlineQueryResultCachedDocumentTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_document):
|
||||
inst = inline_query_result_cached_document
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,19 +32,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_gif():
|
||||
return InlineQueryResultCachedGif(
|
||||
TestInlineQueryResultCachedGifBase.id_,
|
||||
TestInlineQueryResultCachedGifBase.gif_file_id,
|
||||
title=TestInlineQueryResultCachedGifBase.title,
|
||||
caption=TestInlineQueryResultCachedGifBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedGifBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedGifBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultCachedGifBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedGifBase.reply_markup,
|
||||
show_caption_above_media=TestInlineQueryResultCachedGifBase.show_caption_above_media,
|
||||
InlineQueryResultCachedGifTestBase.id_,
|
||||
InlineQueryResultCachedGifTestBase.gif_file_id,
|
||||
title=InlineQueryResultCachedGifTestBase.title,
|
||||
caption=InlineQueryResultCachedGifTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedGifTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedGifTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultCachedGifTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedGifTestBase.reply_markup,
|
||||
show_caption_above_media=InlineQueryResultCachedGifTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedGifBase:
|
||||
class InlineQueryResultCachedGifTestBase:
|
||||
id_ = "id"
|
||||
type_ = "gif"
|
||||
gif_file_id = "gif file id"
|
||||
|
@ -57,7 +57,7 @@ class TestInlineQueryResultCachedGifBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedGifWithoutRequest(TestInlineQueryResultCachedGifBase):
|
||||
class TestInlineQueryResultCachedGifWithoutRequest(InlineQueryResultCachedGifTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_gif):
|
||||
inst = inline_query_result_cached_gif
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,19 +32,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_mpeg4_gif():
|
||||
return InlineQueryResultCachedMpeg4Gif(
|
||||
TestInlineQueryResultCachedMpeg4GifBase.id_,
|
||||
TestInlineQueryResultCachedMpeg4GifBase.mpeg4_file_id,
|
||||
title=TestInlineQueryResultCachedMpeg4GifBase.title,
|
||||
caption=TestInlineQueryResultCachedMpeg4GifBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedMpeg4GifBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedMpeg4GifBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultCachedMpeg4GifBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedMpeg4GifBase.reply_markup,
|
||||
show_caption_above_media=TestInlineQueryResultCachedMpeg4GifBase.show_caption_above_media,
|
||||
InlineQueryResultCachedMpeg4GifTestBase.id_,
|
||||
InlineQueryResultCachedMpeg4GifTestBase.mpeg4_file_id,
|
||||
title=InlineQueryResultCachedMpeg4GifTestBase.title,
|
||||
caption=InlineQueryResultCachedMpeg4GifTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedMpeg4GifTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedMpeg4GifTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultCachedMpeg4GifTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedMpeg4GifTestBase.reply_markup,
|
||||
show_caption_above_media=InlineQueryResultCachedMpeg4GifTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedMpeg4GifBase:
|
||||
class InlineQueryResultCachedMpeg4GifTestBase:
|
||||
id_ = "id"
|
||||
type_ = "mpeg4_gif"
|
||||
mpeg4_file_id = "mpeg4 file id"
|
||||
|
@ -57,7 +57,7 @@ class TestInlineQueryResultCachedMpeg4GifBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedMpeg4GifWithoutRequest(TestInlineQueryResultCachedMpeg4GifBase):
|
||||
class TestInlineQueryResultCachedMpeg4GifWithoutRequest(InlineQueryResultCachedMpeg4GifTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_mpeg4_gif):
|
||||
inst = inline_query_result_cached_mpeg4_gif
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,20 +32,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_photo():
|
||||
return InlineQueryResultCachedPhoto(
|
||||
TestInlineQueryResultCachedPhotoBase.id_,
|
||||
TestInlineQueryResultCachedPhotoBase.photo_file_id,
|
||||
title=TestInlineQueryResultCachedPhotoBase.title,
|
||||
description=TestInlineQueryResultCachedPhotoBase.description,
|
||||
caption=TestInlineQueryResultCachedPhotoBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedPhotoBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedPhotoBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultCachedPhotoBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedPhotoBase.reply_markup,
|
||||
show_caption_above_media=TestInlineQueryResultCachedPhotoBase.show_caption_above_media,
|
||||
InlineQueryResultCachedPhotoTestBase.id_,
|
||||
InlineQueryResultCachedPhotoTestBase.photo_file_id,
|
||||
title=InlineQueryResultCachedPhotoTestBase.title,
|
||||
description=InlineQueryResultCachedPhotoTestBase.description,
|
||||
caption=InlineQueryResultCachedPhotoTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedPhotoTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedPhotoTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultCachedPhotoTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedPhotoTestBase.reply_markup,
|
||||
show_caption_above_media=InlineQueryResultCachedPhotoTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedPhotoBase:
|
||||
class InlineQueryResultCachedPhotoTestBase:
|
||||
id_ = "id"
|
||||
type_ = "photo"
|
||||
photo_file_id = "photo file id"
|
||||
|
@ -59,7 +59,7 @@ class TestInlineQueryResultCachedPhotoBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedPhotoWithoutRequest(TestInlineQueryResultCachedPhotoBase):
|
||||
class TestInlineQueryResultCachedPhotoWithoutRequest(InlineQueryResultCachedPhotoTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_photo):
|
||||
inst = inline_query_result_cached_photo
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -31,14 +31,14 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_sticker():
|
||||
return InlineQueryResultCachedSticker(
|
||||
TestInlineQueryResultCachedStickerBase.id_,
|
||||
TestInlineQueryResultCachedStickerBase.sticker_file_id,
|
||||
input_message_content=TestInlineQueryResultCachedStickerBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedStickerBase.reply_markup,
|
||||
InlineQueryResultCachedStickerTestBase.id_,
|
||||
InlineQueryResultCachedStickerTestBase.sticker_file_id,
|
||||
input_message_content=InlineQueryResultCachedStickerTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedStickerTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedStickerBase:
|
||||
class InlineQueryResultCachedStickerTestBase:
|
||||
id_ = "id"
|
||||
type_ = "sticker"
|
||||
sticker_file_id = "sticker file id"
|
||||
|
@ -46,7 +46,7 @@ class TestInlineQueryResultCachedStickerBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedStickerWithoutRequest(TestInlineQueryResultCachedStickerBase):
|
||||
class TestInlineQueryResultCachedStickerWithoutRequest(InlineQueryResultCachedStickerTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_sticker):
|
||||
inst = inline_query_result_cached_sticker
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,20 +32,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_video():
|
||||
return InlineQueryResultCachedVideo(
|
||||
TestInlineQueryResultCachedVideoBase.id_,
|
||||
TestInlineQueryResultCachedVideoBase.video_file_id,
|
||||
TestInlineQueryResultCachedVideoBase.title,
|
||||
caption=TestInlineQueryResultCachedVideoBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedVideoBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedVideoBase.caption_entities,
|
||||
description=TestInlineQueryResultCachedVideoBase.description,
|
||||
input_message_content=TestInlineQueryResultCachedVideoBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedVideoBase.reply_markup,
|
||||
show_caption_above_media=TestInlineQueryResultCachedVideoBase.show_caption_above_media,
|
||||
InlineQueryResultCachedVideoTestBase.id_,
|
||||
InlineQueryResultCachedVideoTestBase.video_file_id,
|
||||
InlineQueryResultCachedVideoTestBase.title,
|
||||
caption=InlineQueryResultCachedVideoTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedVideoTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedVideoTestBase.caption_entities,
|
||||
description=InlineQueryResultCachedVideoTestBase.description,
|
||||
input_message_content=InlineQueryResultCachedVideoTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedVideoTestBase.reply_markup,
|
||||
show_caption_above_media=InlineQueryResultCachedVideoTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedVideoBase:
|
||||
class InlineQueryResultCachedVideoTestBase:
|
||||
id_ = "id"
|
||||
type_ = "video"
|
||||
video_file_id = "video file id"
|
||||
|
@ -59,7 +59,7 @@ class TestInlineQueryResultCachedVideoBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedVideoWithoutRequest(TestInlineQueryResultCachedVideoBase):
|
||||
class TestInlineQueryResultCachedVideoWithoutRequest(InlineQueryResultCachedVideoTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_video):
|
||||
inst = inline_query_result_cached_video
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,18 +32,18 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_cached_voice():
|
||||
return InlineQueryResultCachedVoice(
|
||||
TestInlineQueryResultCachedVoiceBase.id_,
|
||||
TestInlineQueryResultCachedVoiceBase.voice_file_id,
|
||||
TestInlineQueryResultCachedVoiceBase.title,
|
||||
caption=TestInlineQueryResultCachedVoiceBase.caption,
|
||||
parse_mode=TestInlineQueryResultCachedVoiceBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultCachedVoiceBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultCachedVoiceBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultCachedVoiceBase.reply_markup,
|
||||
InlineQueryResultCachedVoiceTestBase.id_,
|
||||
InlineQueryResultCachedVoiceTestBase.voice_file_id,
|
||||
InlineQueryResultCachedVoiceTestBase.title,
|
||||
caption=InlineQueryResultCachedVoiceTestBase.caption,
|
||||
parse_mode=InlineQueryResultCachedVoiceTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultCachedVoiceTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultCachedVoiceTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultCachedVoiceTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedVoiceBase:
|
||||
class InlineQueryResultCachedVoiceTestBase:
|
||||
id_ = "id"
|
||||
type_ = "voice"
|
||||
voice_file_id = "voice file id"
|
||||
|
@ -55,7 +55,7 @@ class TestInlineQueryResultCachedVoiceBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultCachedVoiceWithoutRequest(TestInlineQueryResultCachedVoiceBase):
|
||||
class TestInlineQueryResultCachedVoiceWithoutRequest(InlineQueryResultCachedVoiceTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_cached_voice):
|
||||
inst = inline_query_result_cached_voice
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -31,19 +31,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_contact():
|
||||
return InlineQueryResultContact(
|
||||
TestInlineQueryResultContactBase.id_,
|
||||
TestInlineQueryResultContactBase.phone_number,
|
||||
TestInlineQueryResultContactBase.first_name,
|
||||
last_name=TestInlineQueryResultContactBase.last_name,
|
||||
thumbnail_url=TestInlineQueryResultContactBase.thumbnail_url,
|
||||
thumbnail_width=TestInlineQueryResultContactBase.thumbnail_width,
|
||||
thumbnail_height=TestInlineQueryResultContactBase.thumbnail_height,
|
||||
input_message_content=TestInlineQueryResultContactBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultContactBase.reply_markup,
|
||||
InlineQueryResultContactTestBase.id_,
|
||||
InlineQueryResultContactTestBase.phone_number,
|
||||
InlineQueryResultContactTestBase.first_name,
|
||||
last_name=InlineQueryResultContactTestBase.last_name,
|
||||
thumbnail_url=InlineQueryResultContactTestBase.thumbnail_url,
|
||||
thumbnail_width=InlineQueryResultContactTestBase.thumbnail_width,
|
||||
thumbnail_height=InlineQueryResultContactTestBase.thumbnail_height,
|
||||
input_message_content=InlineQueryResultContactTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultContactTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultContactBase:
|
||||
class InlineQueryResultContactTestBase:
|
||||
id_ = "id"
|
||||
type_ = "contact"
|
||||
phone_number = "phone_number"
|
||||
|
@ -56,7 +56,7 @@ class TestInlineQueryResultContactBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultContactWithoutRequest(TestInlineQueryResultContactBase):
|
||||
class TestInlineQueryResultContactWithoutRequest(InlineQueryResultContactTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_contact):
|
||||
inst = inline_query_result_contact
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,23 +32,23 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_document():
|
||||
return InlineQueryResultDocument(
|
||||
TestInlineQueryResultDocumentBase.id_,
|
||||
TestInlineQueryResultDocumentBase.document_url,
|
||||
TestInlineQueryResultDocumentBase.title,
|
||||
TestInlineQueryResultDocumentBase.mime_type,
|
||||
caption=TestInlineQueryResultDocumentBase.caption,
|
||||
parse_mode=TestInlineQueryResultDocumentBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultDocumentBase.caption_entities,
|
||||
description=TestInlineQueryResultDocumentBase.description,
|
||||
thumbnail_url=TestInlineQueryResultDocumentBase.thumbnail_url,
|
||||
thumbnail_width=TestInlineQueryResultDocumentBase.thumbnail_width,
|
||||
thumbnail_height=TestInlineQueryResultDocumentBase.thumbnail_height,
|
||||
input_message_content=TestInlineQueryResultDocumentBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultDocumentBase.reply_markup,
|
||||
InlineQueryResultDocumentTestBase.id_,
|
||||
InlineQueryResultDocumentTestBase.document_url,
|
||||
InlineQueryResultDocumentTestBase.title,
|
||||
InlineQueryResultDocumentTestBase.mime_type,
|
||||
caption=InlineQueryResultDocumentTestBase.caption,
|
||||
parse_mode=InlineQueryResultDocumentTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultDocumentTestBase.caption_entities,
|
||||
description=InlineQueryResultDocumentTestBase.description,
|
||||
thumbnail_url=InlineQueryResultDocumentTestBase.thumbnail_url,
|
||||
thumbnail_width=InlineQueryResultDocumentTestBase.thumbnail_width,
|
||||
thumbnail_height=InlineQueryResultDocumentTestBase.thumbnail_height,
|
||||
input_message_content=InlineQueryResultDocumentTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultDocumentTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultDocumentBase:
|
||||
class InlineQueryResultDocumentTestBase:
|
||||
id_ = "id"
|
||||
type_ = "document"
|
||||
document_url = "document url"
|
||||
|
@ -65,7 +65,7 @@ class TestInlineQueryResultDocumentBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultDocumentWithoutRequest(TestInlineQueryResultDocumentBase):
|
||||
class TestInlineQueryResultDocumentWithoutRequest(InlineQueryResultDocumentTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_document):
|
||||
inst = inline_query_result_document
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -30,20 +30,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_game():
|
||||
return InlineQueryResultGame(
|
||||
TestInlineQueryResultGameBase.id_,
|
||||
TestInlineQueryResultGameBase.game_short_name,
|
||||
reply_markup=TestInlineQueryResultGameBase.reply_markup,
|
||||
InlineQueryResultGameTestBase.id_,
|
||||
InlineQueryResultGameTestBase.game_short_name,
|
||||
reply_markup=InlineQueryResultGameTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultGameBase:
|
||||
class InlineQueryResultGameTestBase:
|
||||
id_ = "id"
|
||||
type_ = "game"
|
||||
game_short_name = "game short name"
|
||||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultGameWithoutRequest(TestInlineQueryResultGameBase):
|
||||
class TestInlineQueryResultGameWithoutRequest(InlineQueryResultGameTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_game):
|
||||
inst = inline_query_result_game
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,24 +32,24 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_gif():
|
||||
return InlineQueryResultGif(
|
||||
TestInlineQueryResultGifBase.id_,
|
||||
TestInlineQueryResultGifBase.gif_url,
|
||||
TestInlineQueryResultGifBase.thumbnail_url,
|
||||
gif_width=TestInlineQueryResultGifBase.gif_width,
|
||||
gif_height=TestInlineQueryResultGifBase.gif_height,
|
||||
gif_duration=TestInlineQueryResultGifBase.gif_duration,
|
||||
title=TestInlineQueryResultGifBase.title,
|
||||
caption=TestInlineQueryResultGifBase.caption,
|
||||
parse_mode=TestInlineQueryResultGifBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultGifBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultGifBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultGifBase.reply_markup,
|
||||
thumbnail_mime_type=TestInlineQueryResultGifBase.thumbnail_mime_type,
|
||||
show_caption_above_media=TestInlineQueryResultGifBase.show_caption_above_media,
|
||||
InlineQueryResultGifTestBase.id_,
|
||||
InlineQueryResultGifTestBase.gif_url,
|
||||
InlineQueryResultGifTestBase.thumbnail_url,
|
||||
gif_width=InlineQueryResultGifTestBase.gif_width,
|
||||
gif_height=InlineQueryResultGifTestBase.gif_height,
|
||||
gif_duration=InlineQueryResultGifTestBase.gif_duration,
|
||||
title=InlineQueryResultGifTestBase.title,
|
||||
caption=InlineQueryResultGifTestBase.caption,
|
||||
parse_mode=InlineQueryResultGifTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultGifTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultGifTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultGifTestBase.reply_markup,
|
||||
thumbnail_mime_type=InlineQueryResultGifTestBase.thumbnail_mime_type,
|
||||
show_caption_above_media=InlineQueryResultGifTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultGifBase:
|
||||
class InlineQueryResultGifTestBase:
|
||||
id_ = "id"
|
||||
type_ = "gif"
|
||||
gif_url = "gif url"
|
||||
|
@ -67,7 +67,7 @@ class TestInlineQueryResultGifBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultGifWithoutRequest(TestInlineQueryResultGifBase):
|
||||
class TestInlineQueryResultGifWithoutRequest(InlineQueryResultGifTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_gif):
|
||||
inst = inline_query_result_gif
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -31,23 +31,23 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_location():
|
||||
return InlineQueryResultLocation(
|
||||
TestInlineQueryResultLocationBase.id_,
|
||||
TestInlineQueryResultLocationBase.latitude,
|
||||
TestInlineQueryResultLocationBase.longitude,
|
||||
TestInlineQueryResultLocationBase.title,
|
||||
live_period=TestInlineQueryResultLocationBase.live_period,
|
||||
thumbnail_url=TestInlineQueryResultLocationBase.thumbnail_url,
|
||||
thumbnail_width=TestInlineQueryResultLocationBase.thumbnail_width,
|
||||
thumbnail_height=TestInlineQueryResultLocationBase.thumbnail_height,
|
||||
input_message_content=TestInlineQueryResultLocationBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultLocationBase.reply_markup,
|
||||
horizontal_accuracy=TestInlineQueryResultLocationBase.horizontal_accuracy,
|
||||
heading=TestInlineQueryResultLocationBase.heading,
|
||||
proximity_alert_radius=TestInlineQueryResultLocationBase.proximity_alert_radius,
|
||||
InlineQueryResultLocationTestBase.id_,
|
||||
InlineQueryResultLocationTestBase.latitude,
|
||||
InlineQueryResultLocationTestBase.longitude,
|
||||
InlineQueryResultLocationTestBase.title,
|
||||
live_period=InlineQueryResultLocationTestBase.live_period,
|
||||
thumbnail_url=InlineQueryResultLocationTestBase.thumbnail_url,
|
||||
thumbnail_width=InlineQueryResultLocationTestBase.thumbnail_width,
|
||||
thumbnail_height=InlineQueryResultLocationTestBase.thumbnail_height,
|
||||
input_message_content=InlineQueryResultLocationTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultLocationTestBase.reply_markup,
|
||||
horizontal_accuracy=InlineQueryResultLocationTestBase.horizontal_accuracy,
|
||||
heading=InlineQueryResultLocationTestBase.heading,
|
||||
proximity_alert_radius=InlineQueryResultLocationTestBase.proximity_alert_radius,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultLocationBase:
|
||||
class InlineQueryResultLocationTestBase:
|
||||
id_ = "id"
|
||||
type_ = "location"
|
||||
latitude = 0.0
|
||||
|
@ -64,7 +64,7 @@ class TestInlineQueryResultLocationBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultLocationWithoutRequest(TestInlineQueryResultLocationBase):
|
||||
class TestInlineQueryResultLocationWithoutRequest(InlineQueryResultLocationTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_location):
|
||||
inst = inline_query_result_location
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,24 +32,24 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_mpeg4_gif():
|
||||
return InlineQueryResultMpeg4Gif(
|
||||
TestInlineQueryResultMpeg4GifBase.id_,
|
||||
TestInlineQueryResultMpeg4GifBase.mpeg4_url,
|
||||
TestInlineQueryResultMpeg4GifBase.thumbnail_url,
|
||||
mpeg4_width=TestInlineQueryResultMpeg4GifBase.mpeg4_width,
|
||||
mpeg4_height=TestInlineQueryResultMpeg4GifBase.mpeg4_height,
|
||||
mpeg4_duration=TestInlineQueryResultMpeg4GifBase.mpeg4_duration,
|
||||
title=TestInlineQueryResultMpeg4GifBase.title,
|
||||
caption=TestInlineQueryResultMpeg4GifBase.caption,
|
||||
parse_mode=TestInlineQueryResultMpeg4GifBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultMpeg4GifBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultMpeg4GifBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultMpeg4GifBase.reply_markup,
|
||||
thumbnail_mime_type=TestInlineQueryResultMpeg4GifBase.thumbnail_mime_type,
|
||||
show_caption_above_media=TestInlineQueryResultMpeg4GifBase.show_caption_above_media,
|
||||
InlineQueryResultMpeg4GifTestBase.id_,
|
||||
InlineQueryResultMpeg4GifTestBase.mpeg4_url,
|
||||
InlineQueryResultMpeg4GifTestBase.thumbnail_url,
|
||||
mpeg4_width=InlineQueryResultMpeg4GifTestBase.mpeg4_width,
|
||||
mpeg4_height=InlineQueryResultMpeg4GifTestBase.mpeg4_height,
|
||||
mpeg4_duration=InlineQueryResultMpeg4GifTestBase.mpeg4_duration,
|
||||
title=InlineQueryResultMpeg4GifTestBase.title,
|
||||
caption=InlineQueryResultMpeg4GifTestBase.caption,
|
||||
parse_mode=InlineQueryResultMpeg4GifTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultMpeg4GifTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultMpeg4GifTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultMpeg4GifTestBase.reply_markup,
|
||||
thumbnail_mime_type=InlineQueryResultMpeg4GifTestBase.thumbnail_mime_type,
|
||||
show_caption_above_media=InlineQueryResultMpeg4GifTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultMpeg4GifBase:
|
||||
class InlineQueryResultMpeg4GifTestBase:
|
||||
id_ = "id"
|
||||
type_ = "mpeg4_gif"
|
||||
mpeg4_url = "mpeg4 url"
|
||||
|
@ -67,7 +67,7 @@ class TestInlineQueryResultMpeg4GifBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultMpeg4GifWithoutRequest(TestInlineQueryResultMpeg4GifBase):
|
||||
class TestInlineQueryResultMpeg4GifWithoutRequest(InlineQueryResultMpeg4GifTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_mpeg4_gif):
|
||||
inst = inline_query_result_mpeg4_gif
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,23 +32,23 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_photo():
|
||||
return InlineQueryResultPhoto(
|
||||
TestInlineQueryResultPhotoBase.id_,
|
||||
TestInlineQueryResultPhotoBase.photo_url,
|
||||
TestInlineQueryResultPhotoBase.thumbnail_url,
|
||||
photo_width=TestInlineQueryResultPhotoBase.photo_width,
|
||||
photo_height=TestInlineQueryResultPhotoBase.photo_height,
|
||||
title=TestInlineQueryResultPhotoBase.title,
|
||||
description=TestInlineQueryResultPhotoBase.description,
|
||||
caption=TestInlineQueryResultPhotoBase.caption,
|
||||
parse_mode=TestInlineQueryResultPhotoBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultPhotoBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultPhotoBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultPhotoBase.reply_markup,
|
||||
show_caption_above_media=TestInlineQueryResultPhotoBase.show_caption_above_media,
|
||||
InlineQueryResultPhotoTestBase.id_,
|
||||
InlineQueryResultPhotoTestBase.photo_url,
|
||||
InlineQueryResultPhotoTestBase.thumbnail_url,
|
||||
photo_width=InlineQueryResultPhotoTestBase.photo_width,
|
||||
photo_height=InlineQueryResultPhotoTestBase.photo_height,
|
||||
title=InlineQueryResultPhotoTestBase.title,
|
||||
description=InlineQueryResultPhotoTestBase.description,
|
||||
caption=InlineQueryResultPhotoTestBase.caption,
|
||||
parse_mode=InlineQueryResultPhotoTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultPhotoTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultPhotoTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultPhotoTestBase.reply_markup,
|
||||
show_caption_above_media=InlineQueryResultPhotoTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultPhotoBase:
|
||||
class InlineQueryResultPhotoTestBase:
|
||||
id_ = "id"
|
||||
type_ = "photo"
|
||||
photo_url = "photo url"
|
||||
|
@ -66,7 +66,7 @@ class TestInlineQueryResultPhotoBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultPhotoWithoutRequest(TestInlineQueryResultPhotoBase):
|
||||
class TestInlineQueryResultPhotoWithoutRequest(InlineQueryResultPhotoTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_photo):
|
||||
inst = inline_query_result_photo
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -31,24 +31,24 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_venue():
|
||||
return InlineQueryResultVenue(
|
||||
TestInlineQueryResultVenueBase.id_,
|
||||
TestInlineQueryResultVenueBase.latitude,
|
||||
TestInlineQueryResultVenueBase.longitude,
|
||||
TestInlineQueryResultVenueBase.title,
|
||||
TestInlineQueryResultVenueBase.address,
|
||||
foursquare_id=TestInlineQueryResultVenueBase.foursquare_id,
|
||||
foursquare_type=TestInlineQueryResultVenueBase.foursquare_type,
|
||||
thumbnail_url=TestInlineQueryResultVenueBase.thumbnail_url,
|
||||
thumbnail_width=TestInlineQueryResultVenueBase.thumbnail_width,
|
||||
thumbnail_height=TestInlineQueryResultVenueBase.thumbnail_height,
|
||||
input_message_content=TestInlineQueryResultVenueBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultVenueBase.reply_markup,
|
||||
google_place_id=TestInlineQueryResultVenueBase.google_place_id,
|
||||
google_place_type=TestInlineQueryResultVenueBase.google_place_type,
|
||||
InlineQueryResultVenueTestBase.id_,
|
||||
InlineQueryResultVenueTestBase.latitude,
|
||||
InlineQueryResultVenueTestBase.longitude,
|
||||
InlineQueryResultVenueTestBase.title,
|
||||
InlineQueryResultVenueTestBase.address,
|
||||
foursquare_id=InlineQueryResultVenueTestBase.foursquare_id,
|
||||
foursquare_type=InlineQueryResultVenueTestBase.foursquare_type,
|
||||
thumbnail_url=InlineQueryResultVenueTestBase.thumbnail_url,
|
||||
thumbnail_width=InlineQueryResultVenueTestBase.thumbnail_width,
|
||||
thumbnail_height=InlineQueryResultVenueTestBase.thumbnail_height,
|
||||
input_message_content=InlineQueryResultVenueTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultVenueTestBase.reply_markup,
|
||||
google_place_id=InlineQueryResultVenueTestBase.google_place_id,
|
||||
google_place_type=InlineQueryResultVenueTestBase.google_place_type,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultVenueBase:
|
||||
class InlineQueryResultVenueTestBase:
|
||||
id_ = "id"
|
||||
type_ = "venue"
|
||||
latitude = "latitude"
|
||||
|
@ -66,7 +66,7 @@ class TestInlineQueryResultVenueBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultVenueWithoutRequest(TestInlineQueryResultVenueBase):
|
||||
class TestInlineQueryResultVenueWithoutRequest(InlineQueryResultVenueTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_venue):
|
||||
inst = inline_query_result_venue
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,25 +32,25 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_video():
|
||||
return InlineQueryResultVideo(
|
||||
TestInlineQueryResultVideoBase.id_,
|
||||
TestInlineQueryResultVideoBase.video_url,
|
||||
TestInlineQueryResultVideoBase.mime_type,
|
||||
TestInlineQueryResultVideoBase.thumbnail_url,
|
||||
TestInlineQueryResultVideoBase.title,
|
||||
video_width=TestInlineQueryResultVideoBase.video_width,
|
||||
video_height=TestInlineQueryResultVideoBase.video_height,
|
||||
video_duration=TestInlineQueryResultVideoBase.video_duration,
|
||||
caption=TestInlineQueryResultVideoBase.caption,
|
||||
parse_mode=TestInlineQueryResultVideoBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultVideoBase.caption_entities,
|
||||
description=TestInlineQueryResultVideoBase.description,
|
||||
input_message_content=TestInlineQueryResultVideoBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultVideoBase.reply_markup,
|
||||
show_caption_above_media=TestInlineQueryResultVideoBase.show_caption_above_media,
|
||||
InlineQueryResultVideoTestBase.id_,
|
||||
InlineQueryResultVideoTestBase.video_url,
|
||||
InlineQueryResultVideoTestBase.mime_type,
|
||||
InlineQueryResultVideoTestBase.thumbnail_url,
|
||||
InlineQueryResultVideoTestBase.title,
|
||||
video_width=InlineQueryResultVideoTestBase.video_width,
|
||||
video_height=InlineQueryResultVideoTestBase.video_height,
|
||||
video_duration=InlineQueryResultVideoTestBase.video_duration,
|
||||
caption=InlineQueryResultVideoTestBase.caption,
|
||||
parse_mode=InlineQueryResultVideoTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultVideoTestBase.caption_entities,
|
||||
description=InlineQueryResultVideoTestBase.description,
|
||||
input_message_content=InlineQueryResultVideoTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultVideoTestBase.reply_markup,
|
||||
show_caption_above_media=InlineQueryResultVideoTestBase.show_caption_above_media,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultVideoBase:
|
||||
class InlineQueryResultVideoTestBase:
|
||||
id_ = "id"
|
||||
type_ = "video"
|
||||
video_url = "video url"
|
||||
|
@ -69,7 +69,7 @@ class TestInlineQueryResultVideoBase:
|
|||
show_caption_above_media = True
|
||||
|
||||
|
||||
class TestInlineQueryResultVideoWithoutRequest(TestInlineQueryResultVideoBase):
|
||||
class TestInlineQueryResultVideoWithoutRequest(InlineQueryResultVideoTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_video):
|
||||
inst = inline_query_result_video
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -32,19 +32,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def inline_query_result_voice():
|
||||
return InlineQueryResultVoice(
|
||||
id=TestInlineQueryResultVoiceBase.id_,
|
||||
voice_url=TestInlineQueryResultVoiceBase.voice_url,
|
||||
title=TestInlineQueryResultVoiceBase.title,
|
||||
voice_duration=TestInlineQueryResultVoiceBase.voice_duration,
|
||||
caption=TestInlineQueryResultVoiceBase.caption,
|
||||
parse_mode=TestInlineQueryResultVoiceBase.parse_mode,
|
||||
caption_entities=TestInlineQueryResultVoiceBase.caption_entities,
|
||||
input_message_content=TestInlineQueryResultVoiceBase.input_message_content,
|
||||
reply_markup=TestInlineQueryResultVoiceBase.reply_markup,
|
||||
id=InlineQueryResultVoiceTestBase.id_,
|
||||
voice_url=InlineQueryResultVoiceTestBase.voice_url,
|
||||
title=InlineQueryResultVoiceTestBase.title,
|
||||
voice_duration=InlineQueryResultVoiceTestBase.voice_duration,
|
||||
caption=InlineQueryResultVoiceTestBase.caption,
|
||||
parse_mode=InlineQueryResultVoiceTestBase.parse_mode,
|
||||
caption_entities=InlineQueryResultVoiceTestBase.caption_entities,
|
||||
input_message_content=InlineQueryResultVoiceTestBase.input_message_content,
|
||||
reply_markup=InlineQueryResultVoiceTestBase.reply_markup,
|
||||
)
|
||||
|
||||
|
||||
class TestInlineQueryResultVoiceBase:
|
||||
class InlineQueryResultVoiceTestBase:
|
||||
id_ = "id"
|
||||
type_ = "voice"
|
||||
voice_url = "voice url"
|
||||
|
@ -57,7 +57,7 @@ class TestInlineQueryResultVoiceBase:
|
|||
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
|
||||
|
||||
|
||||
class TestInlineQueryResultVoiceWithoutRequest(TestInlineQueryResultVoiceBase):
|
||||
class TestInlineQueryResultVoiceWithoutRequest(InlineQueryResultVoiceTestBase):
|
||||
def test_slot_behaviour(self, inline_query_result_voice):
|
||||
inst = inline_query_result_voice
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,19 +25,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def input_contact_message_content():
|
||||
return InputContactMessageContent(
|
||||
TestInputContactMessageContentBase.phone_number,
|
||||
TestInputContactMessageContentBase.first_name,
|
||||
TestInputContactMessageContentBase.last_name,
|
||||
InputContactMessageContentTestBase.phone_number,
|
||||
InputContactMessageContentTestBase.first_name,
|
||||
InputContactMessageContentTestBase.last_name,
|
||||
)
|
||||
|
||||
|
||||
class TestInputContactMessageContentBase:
|
||||
class InputContactMessageContentTestBase:
|
||||
phone_number = "phone number"
|
||||
first_name = "first name"
|
||||
last_name = "last name"
|
||||
|
||||
|
||||
class TestInputContactMessageContentWithoutRequest(TestInputContactMessageContentBase):
|
||||
class TestInputContactMessageContentWithoutRequest(InputContactMessageContentTestBase):
|
||||
def test_slot_behaviour(self, input_contact_message_content):
|
||||
inst = input_contact_message_content
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -26,32 +26,32 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def input_invoice_message_content():
|
||||
return InputInvoiceMessageContent(
|
||||
title=TestInputInvoiceMessageContentBase.title,
|
||||
description=TestInputInvoiceMessageContentBase.description,
|
||||
payload=TestInputInvoiceMessageContentBase.payload,
|
||||
provider_token=TestInputInvoiceMessageContentBase.provider_token,
|
||||
currency=TestInputInvoiceMessageContentBase.currency,
|
||||
prices=TestInputInvoiceMessageContentBase.prices,
|
||||
max_tip_amount=TestInputInvoiceMessageContentBase.max_tip_amount,
|
||||
suggested_tip_amounts=TestInputInvoiceMessageContentBase.suggested_tip_amounts,
|
||||
provider_data=TestInputInvoiceMessageContentBase.provider_data,
|
||||
photo_url=TestInputInvoiceMessageContentBase.photo_url,
|
||||
photo_size=TestInputInvoiceMessageContentBase.photo_size,
|
||||
photo_width=TestInputInvoiceMessageContentBase.photo_width,
|
||||
photo_height=TestInputInvoiceMessageContentBase.photo_height,
|
||||
need_name=TestInputInvoiceMessageContentBase.need_name,
|
||||
need_phone_number=TestInputInvoiceMessageContentBase.need_phone_number,
|
||||
need_email=TestInputInvoiceMessageContentBase.need_email,
|
||||
need_shipping_address=TestInputInvoiceMessageContentBase.need_shipping_address,
|
||||
title=InputInvoiceMessageContentTestBase.title,
|
||||
description=InputInvoiceMessageContentTestBase.description,
|
||||
payload=InputInvoiceMessageContentTestBase.payload,
|
||||
provider_token=InputInvoiceMessageContentTestBase.provider_token,
|
||||
currency=InputInvoiceMessageContentTestBase.currency,
|
||||
prices=InputInvoiceMessageContentTestBase.prices,
|
||||
max_tip_amount=InputInvoiceMessageContentTestBase.max_tip_amount,
|
||||
suggested_tip_amounts=InputInvoiceMessageContentTestBase.suggested_tip_amounts,
|
||||
provider_data=InputInvoiceMessageContentTestBase.provider_data,
|
||||
photo_url=InputInvoiceMessageContentTestBase.photo_url,
|
||||
photo_size=InputInvoiceMessageContentTestBase.photo_size,
|
||||
photo_width=InputInvoiceMessageContentTestBase.photo_width,
|
||||
photo_height=InputInvoiceMessageContentTestBase.photo_height,
|
||||
need_name=InputInvoiceMessageContentTestBase.need_name,
|
||||
need_phone_number=InputInvoiceMessageContentTestBase.need_phone_number,
|
||||
need_email=InputInvoiceMessageContentTestBase.need_email,
|
||||
need_shipping_address=InputInvoiceMessageContentTestBase.need_shipping_address,
|
||||
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,
|
||||
is_flexible=TestInputInvoiceMessageContentBase.is_flexible,
|
||||
send_email_to_provider=InputInvoiceMessageContentTestBase.send_email_to_provider,
|
||||
is_flexible=InputInvoiceMessageContentTestBase.is_flexible,
|
||||
)
|
||||
|
||||
|
||||
class TestInputInvoiceMessageContentBase:
|
||||
class InputInvoiceMessageContentTestBase:
|
||||
title = "invoice title"
|
||||
description = "invoice description"
|
||||
payload = "invoice payload"
|
||||
|
@ -74,7 +74,7 @@ class TestInputInvoiceMessageContentBase:
|
|||
is_flexible = True
|
||||
|
||||
|
||||
class TestInputInvoiceMessageContentWithoutRequest(TestInputInvoiceMessageContentBase):
|
||||
class TestInputInvoiceMessageContentWithoutRequest(InputInvoiceMessageContentTestBase):
|
||||
def test_slot_behaviour(self, input_invoice_message_content):
|
||||
inst = input_invoice_message_content
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,16 +25,16 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def input_location_message_content():
|
||||
return InputLocationMessageContent(
|
||||
TestInputLocationMessageContentBase.latitude,
|
||||
TestInputLocationMessageContentBase.longitude,
|
||||
live_period=TestInputLocationMessageContentBase.live_period,
|
||||
horizontal_accuracy=TestInputLocationMessageContentBase.horizontal_accuracy,
|
||||
heading=TestInputLocationMessageContentBase.heading,
|
||||
proximity_alert_radius=TestInputLocationMessageContentBase.proximity_alert_radius,
|
||||
InputLocationMessageContentTestBase.latitude,
|
||||
InputLocationMessageContentTestBase.longitude,
|
||||
live_period=InputLocationMessageContentTestBase.live_period,
|
||||
horizontal_accuracy=InputLocationMessageContentTestBase.horizontal_accuracy,
|
||||
heading=InputLocationMessageContentTestBase.heading,
|
||||
proximity_alert_radius=InputLocationMessageContentTestBase.proximity_alert_radius,
|
||||
)
|
||||
|
||||
|
||||
class TestInputLocationMessageContentBase:
|
||||
class InputLocationMessageContentTestBase:
|
||||
latitude = -23.691288
|
||||
longitude = -46.788279
|
||||
live_period = 80
|
||||
|
@ -43,7 +43,7 @@ class TestInputLocationMessageContentBase:
|
|||
proximity_alert_radius = 999
|
||||
|
||||
|
||||
class TestInputLocationMessageContentWithoutRequest(TestInputLocationMessageContentBase):
|
||||
class TestInputLocationMessageContentWithoutRequest(InputLocationMessageContentTestBase):
|
||||
def test_slot_behaviour(self, input_location_message_content):
|
||||
inst = input_location_message_content
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -26,14 +26,14 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def input_text_message_content():
|
||||
return InputTextMessageContent(
|
||||
TestInputTextMessageContentBase.message_text,
|
||||
parse_mode=TestInputTextMessageContentBase.parse_mode,
|
||||
entities=TestInputTextMessageContentBase.entities,
|
||||
link_preview_options=TestInputTextMessageContentBase.link_preview_options,
|
||||
InputTextMessageContentTestBase.message_text,
|
||||
parse_mode=InputTextMessageContentTestBase.parse_mode,
|
||||
entities=InputTextMessageContentTestBase.entities,
|
||||
link_preview_options=InputTextMessageContentTestBase.link_preview_options,
|
||||
)
|
||||
|
||||
|
||||
class TestInputTextMessageContentBase:
|
||||
class InputTextMessageContentTestBase:
|
||||
message_text = "*message text*"
|
||||
parse_mode = ParseMode.MARKDOWN
|
||||
entities = [MessageEntity(MessageEntity.ITALIC, 0, 7)]
|
||||
|
@ -41,7 +41,7 @@ class TestInputTextMessageContentBase:
|
|||
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):
|
||||
inst = input_text_message_content
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,18 +25,18 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def input_venue_message_content():
|
||||
return InputVenueMessageContent(
|
||||
TestInputVenueMessageContentBase.latitude,
|
||||
TestInputVenueMessageContentBase.longitude,
|
||||
TestInputVenueMessageContentBase.title,
|
||||
TestInputVenueMessageContentBase.address,
|
||||
foursquare_id=TestInputVenueMessageContentBase.foursquare_id,
|
||||
foursquare_type=TestInputVenueMessageContentBase.foursquare_type,
|
||||
google_place_id=TestInputVenueMessageContentBase.google_place_id,
|
||||
google_place_type=TestInputVenueMessageContentBase.google_place_type,
|
||||
InputVenueMessageContentTestBase.latitude,
|
||||
InputVenueMessageContentTestBase.longitude,
|
||||
InputVenueMessageContentTestBase.title,
|
||||
InputVenueMessageContentTestBase.address,
|
||||
foursquare_id=InputVenueMessageContentTestBase.foursquare_id,
|
||||
foursquare_type=InputVenueMessageContentTestBase.foursquare_type,
|
||||
google_place_id=InputVenueMessageContentTestBase.google_place_id,
|
||||
google_place_type=InputVenueMessageContentTestBase.google_place_type,
|
||||
)
|
||||
|
||||
|
||||
class TestInputVenueMessageContentBase:
|
||||
class InputVenueMessageContentTestBase:
|
||||
latitude = 1.0
|
||||
longitude = 2.0
|
||||
title = "title"
|
||||
|
@ -47,7 +47,7 @@ class TestInputVenueMessageContentBase:
|
|||
google_place_type = "google place type"
|
||||
|
||||
|
||||
class TestInputVenueMessageContentWithoutRequest(TestInputVenueMessageContentBase):
|
||||
class TestInputVenueMessageContentWithoutRequest(InputVenueMessageContentTestBase):
|
||||
def test_slot_behaviour(self, input_venue_message_content):
|
||||
inst = input_venue_message_content
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -26,19 +26,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def encrypted_credentials():
|
||||
return EncryptedCredentials(
|
||||
TestEncryptedCredentialsBase.data,
|
||||
TestEncryptedCredentialsBase.hash,
|
||||
TestEncryptedCredentialsBase.secret,
|
||||
EncryptedCredentialsTestBase.data,
|
||||
EncryptedCredentialsTestBase.hash,
|
||||
EncryptedCredentialsTestBase.secret,
|
||||
)
|
||||
|
||||
|
||||
class TestEncryptedCredentialsBase:
|
||||
class EncryptedCredentialsTestBase:
|
||||
data = "data"
|
||||
hash = "hash"
|
||||
secret = "secret"
|
||||
|
||||
|
||||
class TestEncryptedCredentialsWithoutRequest(TestEncryptedCredentialsBase):
|
||||
class TestEncryptedCredentialsWithoutRequest(EncryptedCredentialsTestBase):
|
||||
def test_slot_behaviour(self, encrypted_credentials):
|
||||
inst = encrypted_credentials
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -26,19 +26,19 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def encrypted_passport_element():
|
||||
return EncryptedPassportElement(
|
||||
TestEncryptedPassportElementBase.type_,
|
||||
EncryptedPassportElementTestBase.type_,
|
||||
"this is a hash",
|
||||
data=TestEncryptedPassportElementBase.data,
|
||||
phone_number=TestEncryptedPassportElementBase.phone_number,
|
||||
email=TestEncryptedPassportElementBase.email,
|
||||
files=TestEncryptedPassportElementBase.files,
|
||||
front_side=TestEncryptedPassportElementBase.front_side,
|
||||
reverse_side=TestEncryptedPassportElementBase.reverse_side,
|
||||
selfie=TestEncryptedPassportElementBase.selfie,
|
||||
data=EncryptedPassportElementTestBase.data,
|
||||
phone_number=EncryptedPassportElementTestBase.phone_number,
|
||||
email=EncryptedPassportElementTestBase.email,
|
||||
files=EncryptedPassportElementTestBase.files,
|
||||
front_side=EncryptedPassportElementTestBase.front_side,
|
||||
reverse_side=EncryptedPassportElementTestBase.reverse_side,
|
||||
selfie=EncryptedPassportElementTestBase.selfie,
|
||||
)
|
||||
|
||||
|
||||
class TestEncryptedPassportElementBase:
|
||||
class EncryptedPassportElementTestBase:
|
||||
type_ = "type"
|
||||
hash = "this is a hash"
|
||||
data = "data"
|
||||
|
@ -50,7 +50,7 @@ class TestEncryptedPassportElementBase:
|
|||
selfie = PassportFile("file_id", 50, 0, 25)
|
||||
|
||||
|
||||
class TestEncryptedPassportElementWithoutRequest(TestEncryptedPassportElementBase):
|
||||
class TestEncryptedPassportElementWithoutRequest(EncryptedPassportElementTestBase):
|
||||
def test_slot_behaviour(self, encrypted_passport_element):
|
||||
inst = encrypted_passport_element
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -220,7 +220,7 @@ def passport_data(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_unique_id = "d4e390cca57b4da5a65322b304762a12"
|
||||
driver_license_front_side_file_id = "DgADBAADxwMAApnQgVPK2-ckL2eXVAI"
|
||||
|
@ -243,7 +243,7 @@ class TestPassportBase:
|
|||
driver_license_selfie_credentials_secret = "tivdId6RNYNsvXYPppdzrbxOBuBOr9wXRPDcCvnXU7E="
|
||||
|
||||
|
||||
class TestPassportWithoutRequest(TestPassportBase):
|
||||
class TestPassportWithoutRequest(PassportTestBase):
|
||||
def test_slot_behaviour(self, passport_data):
|
||||
inst = passport_data
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,14 +25,14 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_data_field():
|
||||
return PassportElementErrorDataField(
|
||||
TestPassportElementErrorDataFieldBase.type_,
|
||||
TestPassportElementErrorDataFieldBase.field_name,
|
||||
TestPassportElementErrorDataFieldBase.data_hash,
|
||||
TestPassportElementErrorDataFieldBase.message,
|
||||
PassportElementErrorDataFieldTestBase.type_,
|
||||
PassportElementErrorDataFieldTestBase.field_name,
|
||||
PassportElementErrorDataFieldTestBase.data_hash,
|
||||
PassportElementErrorDataFieldTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorDataFieldBase:
|
||||
class PassportElementErrorDataFieldTestBase:
|
||||
source = "data"
|
||||
type_ = "test_type"
|
||||
field_name = "test_field"
|
||||
|
@ -40,7 +40,7 @@ class TestPassportElementErrorDataFieldBase:
|
|||
message = "Error message"
|
||||
|
||||
|
||||
class TestPassportElementErrorDataFieldWithoutRequest(TestPassportElementErrorDataFieldBase):
|
||||
class TestPassportElementErrorDataFieldWithoutRequest(PassportElementErrorDataFieldTestBase):
|
||||
def test_slot_behaviour(self, passport_element_error_data_field):
|
||||
inst = passport_element_error_data_field
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_file():
|
||||
return PassportElementErrorFile(
|
||||
TestPassportElementErrorFileBase.type_,
|
||||
TestPassportElementErrorFileBase.file_hash,
|
||||
TestPassportElementErrorFileBase.message,
|
||||
PassportElementErrorFileTestBase.type_,
|
||||
PassportElementErrorFileTestBase.file_hash,
|
||||
PassportElementErrorFileTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorFileBase:
|
||||
class PassportElementErrorFileTestBase:
|
||||
source = "file"
|
||||
type_ = "test_type"
|
||||
file_hash = "file_hash"
|
||||
message = "Error message"
|
||||
|
||||
|
||||
class TestPassportElementErrorFileWithoutRequest(TestPassportElementErrorFileBase):
|
||||
class TestPassportElementErrorFileWithoutRequest(PassportElementErrorFileTestBase):
|
||||
def test_slot_behaviour(self, passport_element_error_file):
|
||||
inst = passport_element_error_file
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -26,20 +26,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_files():
|
||||
return PassportElementErrorFiles(
|
||||
TestPassportElementErrorFilesBase.type_,
|
||||
TestPassportElementErrorFilesBase.file_hashes,
|
||||
TestPassportElementErrorFilesBase.message,
|
||||
PassportElementErrorFilesTestBase.type_,
|
||||
PassportElementErrorFilesTestBase.file_hashes,
|
||||
PassportElementErrorFilesTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorFilesBase:
|
||||
class PassportElementErrorFilesTestBase:
|
||||
source = "files"
|
||||
type_ = "test_type"
|
||||
file_hashes = ["hash1", "hash2"]
|
||||
message = "Error message"
|
||||
|
||||
|
||||
class TestPassportElementErrorFilesWithoutRequest(TestPassportElementErrorFilesBase):
|
||||
class TestPassportElementErrorFilesWithoutRequest(PassportElementErrorFilesTestBase):
|
||||
def test_slot_behaviour(self, passport_element_error_files):
|
||||
inst = passport_element_error_files
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_front_side():
|
||||
return PassportElementErrorFrontSide(
|
||||
TestPassportElementErrorFrontSideBase.type_,
|
||||
TestPassportElementErrorFrontSideBase.file_hash,
|
||||
TestPassportElementErrorFrontSideBase.message,
|
||||
PassportElementErrorFrontSideTestBase.type_,
|
||||
PassportElementErrorFrontSideTestBase.file_hash,
|
||||
PassportElementErrorFrontSideTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorFrontSideBase:
|
||||
class PassportElementErrorFrontSideTestBase:
|
||||
source = "front_side"
|
||||
type_ = "test_type"
|
||||
file_hash = "file_hash"
|
||||
message = "Error message"
|
||||
|
||||
|
||||
class TestPassportElementErrorFrontSideWithoutRequest(TestPassportElementErrorFrontSideBase):
|
||||
class TestPassportElementErrorFrontSideWithoutRequest(PassportElementErrorFrontSideTestBase):
|
||||
def test_slot_behaviour(self, passport_element_error_front_side):
|
||||
inst = passport_element_error_front_side
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_reverse_side():
|
||||
return PassportElementErrorReverseSide(
|
||||
TestPassportElementErrorReverseSideBase.type_,
|
||||
TestPassportElementErrorReverseSideBase.file_hash,
|
||||
TestPassportElementErrorReverseSideBase.message,
|
||||
PassportElementErrorReverseSideTestBase.type_,
|
||||
PassportElementErrorReverseSideTestBase.file_hash,
|
||||
PassportElementErrorReverseSideTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorReverseSideBase:
|
||||
class PassportElementErrorReverseSideTestBase:
|
||||
source = "reverse_side"
|
||||
type_ = "test_type"
|
||||
file_hash = "file_hash"
|
||||
message = "Error message"
|
||||
|
||||
|
||||
class TestPassportElementErrorReverseSideWithoutRequest(TestPassportElementErrorReverseSideBase):
|
||||
class TestPassportElementErrorReverseSideWithoutRequest(PassportElementErrorReverseSideTestBase):
|
||||
def test_slot_behaviour(self, passport_element_error_reverse_side):
|
||||
inst = passport_element_error_reverse_side
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,20 +25,20 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_selfie():
|
||||
return PassportElementErrorSelfie(
|
||||
TestPassportElementErrorSelfieBase.type_,
|
||||
TestPassportElementErrorSelfieBase.file_hash,
|
||||
TestPassportElementErrorSelfieBase.message,
|
||||
PassportElementErrorSelfieTestBase.type_,
|
||||
PassportElementErrorSelfieTestBase.file_hash,
|
||||
PassportElementErrorSelfieTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorSelfieBase:
|
||||
class PassportElementErrorSelfieTestBase:
|
||||
source = "selfie"
|
||||
type_ = "test_type"
|
||||
file_hash = "file_hash"
|
||||
message = "Error message"
|
||||
|
||||
|
||||
class TestPassportElementErrorSelfieWithoutRequest(TestPassportElementErrorSelfieBase):
|
||||
class TestPassportElementErrorSelfieWithoutRequest(PassportElementErrorSelfieTestBase):
|
||||
def test_slot_behaviour(self, passport_element_error_selfie):
|
||||
inst = passport_element_error_selfie
|
||||
for attr in inst.__slots__:
|
||||
|
|
|
@ -25,13 +25,13 @@ from tests.auxil.slots import mro_slots
|
|||
@pytest.fixture(scope="module")
|
||||
def passport_element_error_translation_file():
|
||||
return PassportElementErrorTranslationFile(
|
||||
TestPassportElementErrorTranslationFileBase.type_,
|
||||
TestPassportElementErrorTranslationFileBase.file_hash,
|
||||
TestPassportElementErrorTranslationFileBase.message,
|
||||
PassportElementErrorTranslationFileTestBase.type_,
|
||||
PassportElementErrorTranslationFileTestBase.file_hash,
|
||||
PassportElementErrorTranslationFileTestBase.message,
|
||||
)
|
||||
|
||||
|
||||
class TestPassportElementErrorTranslationFileBase:
|
||||
class PassportElementErrorTranslationFileTestBase:
|
||||
source = "translation_file"
|
||||
type_ = "test_type"
|
||||
file_hash = "file_hash"
|
||||
|
@ -39,7 +39,7 @@ class TestPassportElementErrorTranslationFileBase:
|
|||
|
||||
|
||||
class TestPassportElementErrorTranslationFileWithoutRequest(
|
||||
TestPassportElementErrorTranslationFileBase
|
||||
PassportElementErrorTranslationFileTestBase
|
||||
):
|
||||
def test_slot_behaviour(self, 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