Merge remote-tracking branch 'origin/doc-fixes' into doc-fixes

This commit is contained in:
poolitzer 2021-03-01 20:31:31 +01:00
commit f462ba3d8b
92 changed files with 2074 additions and 1503 deletions
.github/workflows
.pre-commit-config.yamlCHANGES.rstREADME.rstREADME_RAW.rst
docs
examples
requirements-dev.txtrequirements.txtsetup.cfgsetup.py
telegram
tests

View file

@ -15,13 +15,6 @@ jobs:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
python-version: 3.7
test-build: True
- os: windows-latest
python-version: 3.7
test-build: True
fail-fast: False
steps:
- uses: actions/checkout@v2
@ -40,18 +33,30 @@ jobs:
python -W ignore -m pip install -r requirements-dev.txt
- name: Test with pytest
# We run 3 different suites here
# 1. Test just utils.helpers.py without pytz being installed
# 2. Test just test_no_passport.py without passport dependencies being installed
# 3. Test everything else
# The first & second one are achieved by mocking the corresponding import
# See test_helpers.py & test_no_passport.py for details
run: |
pytest -v -m nocoverage
nocov_exit=$?
pytest -v -m "not nocoverage" --cov
cov_exit=$?
global_exit=$(( nocov_exit > cov_exit ? nocov_exit : cov_exit ))
pytest -v --cov -k test_no_passport.py
no_passport_exit=$?
export TEST_NO_PASSPORT='false'
pytest -v --cov --cov-append -k test_helpers.py
no_pytz_exit=$?
export TEST_NO_PYTZ='false'
pytest -v --cov --cov-append
full_exit=$?
special_exit=$(( no_pytz_exit > no_passport_exit ? no_pytz_exit : no_passport_exit ))
global_exit=$(( special_exit > full_exit ? special_exit : full_exit ))
exit ${global_exit}
env:
JOB_INDEX: ${{ strategy.job-index }}
BOTS: W3sidG9rZW4iOiAiNjk2MTg4NzMyOkFBR1Z3RUtmSEhsTmpzY3hFRE5LQXdraEdzdFpfa28xbUMwIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WldGaU1UUmxNbVF5TnpNeSIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIENQeXRob24gMi43IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMzkwOTgzOTk3IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19jcHl0aG9uXzI3X2JvdCJ9LCB7InRva2VuIjogIjY3MTQ2ODg4NjpBQUdQR2ZjaVJJQlVORmU4MjR1SVZkcTdKZTNfWW5BVE5HdyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOlpHWXdPVGxrTXpNeE4yWTIiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIFRyYXZpcyB1c2luZyBDUHl0aG9uIDMuNCIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTQ0NjAyMjUyMiIsICJib3RfdXNlcm5hbWUiOiAiQHB0Yl90cmF2aXNfY3B5dGhvbl8zNF9ib3QifSwgeyJ0b2tlbiI6ICI2MjkzMjY1Mzg6QUFGUnJaSnJCN29CM211ekdzR0pYVXZHRTVDUXpNNUNVNG8iLCAicGF5bWVudF9wcm92aWRlcl90b2tlbiI6ICIyODQ2ODUwNjM6VEVTVDpNbU01WVdKaFl6a3hNMlUxIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBvbiBUcmF2aXMgdXNpbmcgQ1B5dGhvbiAzLjUiLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDE0OTY5MTc3NTAiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfdHJhdmlzX2NweXRob25fMzVfYm90In0sIHsidG9rZW4iOiAiNjQwMjA4OTQzOkFBRmhCalFwOXFtM1JUeFN6VXBZekJRakNsZS1Kano1aGNrIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WXpoa1pUZzFOamMxWXpWbCIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIENQeXRob24gMy42IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMzMzODcxNDYxIiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19jcHl0aG9uXzM2X2JvdCJ9LCB7InRva2VuIjogIjY5NTEwNDA4ODpBQUhmenlsSU9qU0lJUy1lT25JMjB5MkUyMEhvZEhzZnotMCIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOk9HUTFNRGd3WmpJd1pqRmwiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIFRyYXZpcyB1c2luZyBDUHl0aG9uIDMuNyIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTQ3ODI5MzcxNCIsICJib3RfdXNlcm5hbWUiOiAiQHB0Yl90cmF2aXNfY3B5dGhvbl8zN19ib3QifSwgeyJ0b2tlbiI6ICI2OTE0MjM1NTQ6QUFGOFdrakNaYm5IcVBfaTZHaFRZaXJGRWxackdhWU9oWDAiLCAicGF5bWVudF9wcm92aWRlcl90b2tlbiI6ICIyODQ2ODUwNjM6VEVTVDpZamM1TlRoaU1tUXlNV1ZoIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBvbiBUcmF2aXMgdXNpbmcgUHlQeSAyLjciLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDEzNjM5MzI1NzMiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfdHJhdmlzX3B5cHlfMjdfYm90In0sIHsidG9rZW4iOiAiNjg0MzM5OTg0OkFBRk1nRUVqcDAxcjVyQjAwN3lDZFZOc2c4QWxOc2FVLWNjIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TVRBek1UWTNNR1V5TmpnMCIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIFB5UHkgMy41IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDA3ODM2NjA1IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19weXB5XzM1X2JvdCJ9LCB7InRva2VuIjogIjY5MDA5MTM0NzpBQUZMbVI1cEFCNVljcGVfbU9oN3pNNEpGQk9oMHozVDBUbyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOlpEaGxOekU1TURrd1lXSmkiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIEFwcFZleW9yIHVzaW5nIENQeXRob24gMy40IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMjc5NjAwMDI2IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX2FwcHZleW9yX2NweXRob25fMzRfYm90In0sIHsidG9rZW4iOiAiNjk0MzA4MDUyOkFBRUIyX3NvbkNrNTVMWTlCRzlBTy1IOGp4aVBTNTVvb0JBIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WW1aaVlXWm1NakpoWkdNeSIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gQXBwVmV5b3IgdXNpbmcgQ1B5dGhvbiAyLjciLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDEyOTMwNzkxNjUiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfYXBwdmV5b3JfY3B5dGhvbl8yN19ib3QifSwgeyJ0b2tlbiI6ICIxMDU1Mzk3NDcxOkFBRzE4bkJfUzJXQXd1SjNnN29oS0JWZ1hYY2VNbklPeVNjIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TmpBd056QXpZalZpTkdOayIsICJuYW1lIjogIlBUQiB0ZXN0cyBbMF0iLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDExODU1MDk2MzYiLCAidXNlcm5hbWUiOiAicHRiXzBfYm90In0sIHsidG9rZW4iOiAiMTA0NzMyNjc3MTpBQUY4bk90ODFGcFg4bGJidno4VWV3UVF2UmZUYkZmQnZ1SSIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOllUVTFOVEk0WkdSallqbGkiLCAibmFtZSI6ICJQVEIgdGVzdHMgWzFdIiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDg0Nzk3NjEyIiwgInVzZXJuYW1lIjogInB0Yl8xX2JvdCJ9LCB7InRva2VuIjogIjk3MTk5Mjc0NTpBQUdPa09hVzBOSGpnSXY1LTlqUWJPajR2R3FkaFNGLVV1cyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOk5XWmtNV1ZoWWpsallqVTUiLCAibmFtZSI6ICJQVEIgdGVzdHMgWzJdIiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDAyMjU1MDcwIiwgInVzZXJuYW1lIjogInB0Yl8yX2JvdCJ9XQ==
TEST_BUILD: ${{ matrix.test-build }}
TEST_PRE_COMMIT: ${{ matrix.test-pre-commit }}
TEST_NO_PYTZ : "true"
TEST_NO_PASSPORT: "true"
TEST_BUILD: "true"
shell: bash --noprofile --norc {0}
- name: Submit coverage

View file

@ -21,12 +21,12 @@ repos:
args:
- --rcfile=setup.cfg
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.790
rev: v0.800
hooks:
- id: mypy
files: ^(telegram|examples)/.*\.py$
- repo: https://github.com/asottile/pyupgrade
rev: v2.7.4
rev: v2.10.0
hooks:
- id: pyupgrade
files: ^(telegram|examples|tests)/.*\.py$

View file

@ -2,6 +2,31 @@
Changelog
=========
Version 13.3
============
*Released 2021-02-19*
**Major Changes:**
- Make ``cryptography`` Dependency Optional & Refactor Some Tests (`#2386`_, `#2370`_)
- Deprecate ``MessageQueue`` (`#2393`_)
**Bug Fixes:**
- Refactor ``Defaults`` Integration (`#2363`_)
- Add Missing ``telegram.SecureValue`` to init and Docs (`#2398`_)
**Minor changes:**
- Doc Fixes (`#2359`_)
.. _`#2386`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2386
.. _`#2370`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2370
.. _`#2393`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2393
.. _`#2363`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2363
.. _`#2398`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2398
.. _`#2359`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2359
Version 13.2
============
*Released 2021-02-02*

View file

@ -137,6 +137,16 @@ In case you have a previously cloned local repository already, you should initia
$ git submodule update --init --recursive
---------------------
Optional Dependencies
---------------------
PTB can be installed with optional dependencies:
* ``pip install python-telegram-bot[passport]`` installs the `cryptography <https://cryptography.io>`_ library. Use this, if you want to use Telegram Passport related functionality.
* ``pip install python-telegram-bot[ujson]`` installs the `ujson <https://pypi.org/project/ujson/>`_ library. It will then be used for JSON de- & encoding, which can bring speed up compared to the standard `json <https://docs.python.org/3/library/json.html>`_ library.
* ``pip install python-telegram-bot[socks]`` installs the `PySocks <https://pypi.org/project/PySocks/>`_ library. Use this, if you want to work behind a Socks5 server.
===============
Getting started
===============

View file

@ -137,6 +137,15 @@ Note
Installing the `.tar.gz` archive available on PyPi directly via `pip` will *not* work as expected, as `pip` does not recognize that it should use `setup-raw.py` instead of `setup.py`.
---------------------
Optional Dependencies
---------------------
PTB can be installed with optional dependencies:
* ``pip install python-telegram-bot-raw[passport]`` installs the `cryptography <https://cryptography.io>`_ library. Use this, if you want to use Telegram Passport related functionality.
* ``pip install python-telegram-bot-raw[ujson]`` installs the `ujson <https://pypi.org/project/ujson/>`_ library. It will then be used for JSON de- & encoding, which can bring speed up compared to the standard `json <https://docs.python.org/3/library/json.html>`_ library.
===============
Getting started
===============

View file

@ -1,3 +1,3 @@
sphinx>=1.7.9
sphinx==3.5.1
sphinx_rtd_theme
sphinx-pypi-upload

View file

@ -33,6 +33,9 @@ extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon'
]
# Don't show type hints in the signature - that just makes it hardly readable
# and we document the types anyway
autodoc_typehints = 'none'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -58,9 +61,9 @@ author = u'Leandro Toledo'
# built documents.
#
# The short X.Y version.
version = '13.2' # telegram.__version__[:3]
version = '13.3' # telegram.__version__[:3]
# The full version, including alpha/beta/rc tags.
release = '13.2' # telegram.__version__
release = '13.3' # telegram.__version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View file

@ -140,6 +140,7 @@ Passport
telegram.credentials
telegram.datacredentials
telegram.securedata
telegram.securevalue
telegram.filecredentials
telegram.iddocumentdata
telegram.personaldetails

View file

@ -0,0 +1,6 @@
telegram.SecureValue
====================
.. autoclass:: telegram.SecureValue
:members:
:show-inheritance:

View file

@ -122,7 +122,7 @@ def done(update: Update, context: CallbackContext) -> None:
del context.user_data['choice']
update.message.reply_text(
"I learned these facts about you:" f"{facts_to_str(context.user_data)}" "Until next time!"
"I learned these facts about you:" f"{facts_to_str(context.user_data)} Until next time!"
)
return ConversationHandler.END

View file

@ -148,7 +148,7 @@ def receive_poll(update: Update, context: CallbackContext) -> None:
def help_handler(update: Update, context: CallbackContext) -> None:
"""Display a help message"""
update.message.reply_text("Use /quiz, /poll or /preview to test this " "bot.")
update.message.reply_text("Use /quiz, /poll or /preview to test this bot.")
def main() -> None:

View file

@ -1,14 +1,15 @@
# cryptography is an optional dependency, but running the tests properly requires it
cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3
pre-commit
# Make sure that the versions specified here match the pre-commit settings
black==20.8b1
flake8==3.8.4
pylint==2.6.0
mypy==0.790
pyupgrade==2.7.4
mypy==0.800
pyupgrade==2.10.0
pytest==4.2.0
# Need older attrs version for pytest 4.2.0
attrs==19.1.0
pytest==6.2.2
flaky
beautifulsoup4

View file

@ -1,5 +1,4 @@
certifi
cryptography
# only telegram.ext: # Keep this line here; used in setup(-raw).py
tornado>=5.1
APScheduler==3.6.3

View file

@ -27,7 +27,9 @@ addopts = --no-success-flaky-report -rsxX
filterwarnings =
error
ignore::DeprecationWarning
ignore::telegram.utils.deprecate.TelegramDeprecationWarning
; Unfortunately due to https://github.com/pytest-dev/pytest/issues/8343 we can't have this here
; and instead do a trick directly in tests/conftest.py
; ignore::telegram.utils.deprecate.TelegramDeprecationWarning
[coverage:run]
branch = True

View file

@ -84,7 +84,9 @@ def get_setup_kwargs(raw=False):
install_requires=requirements,
extras_require={
'json': 'ujson',
'socks': 'PySocks'
'socks': 'PySocks',
# 3.4-3.4.3 contained some cyclical import bugs
'passport': 'cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3',
},
include_package_data=True,
classifiers=[

View file

@ -139,6 +139,7 @@ from .passport.credentials import (
Credentials,
DataCredentials,
SecureData,
SecureValue,
FileCredentials,
TelegramDecryptionError,
)
@ -147,24 +148,37 @@ from .version import __version__ # noqa: F401
__author__ = 'devs@python-telegram-bot.org'
__all__ = [
__all__ = ( # Keep this alphabetically ordered
'Animation',
'Audio',
'Bot',
'BotCommand',
'CallbackGame',
'CallbackQuery',
'Chat',
'ChatAction',
'ChatLocation',
'ChatMember',
'ChatPermissions',
'ChatAction',
'ChatPhoto',
'ChosenInlineResult',
'CallbackQuery',
'Contact',
'Credentials',
'DataCredentials',
'Dice',
'Document',
'EncryptedCredentials',
'EncryptedPassportElement',
'File',
'FileCredentials',
'ForceReply',
'Game',
'GameHighScore',
'IdDocumentData',
'InlineKeyboardButton',
'InlineKeyboardMarkup',
'InlineQuery',
'InlineQueryResult',
'InlineQueryResult',
'InlineQueryResultArticle',
'InlineQueryResultAudio',
'InlineQueryResultCachedAudio',
@ -177,6 +191,7 @@ __all__ = [
'InlineQueryResultCachedVoice',
'InlineQueryResultContact',
'InlineQueryResultDocument',
'InlineQueryResultGame',
'InlineQueryResultGif',
'InlineQueryResultLocation',
'InlineQueryResultMpeg4Gif',
@ -184,28 +199,70 @@ __all__ = [
'InlineQueryResultVenue',
'InlineQueryResultVideo',
'InlineQueryResultVoice',
'InlineQueryResultGame',
'InputContactMessageContent',
'InputFile',
'InputLocationMessageContent',
'InputMedia',
'InputMediaAnimation',
'InputMediaAudio',
'InputMediaDocument',
'InputMediaPhoto',
'InputMediaVideo',
'InputMessageContent',
'InputTextMessageContent',
'InputVenueMessageContent',
'Invoice',
'KeyboardButton',
'KeyboardButtonPollType',
'LabeledPrice',
'Location',
'ChatLocation',
'ProximityAlertTriggered',
'EncryptedCredentials',
'PassportFile',
'EncryptedPassportElement',
'PassportData',
'LoginUrl',
'MAX_CAPTION_LENGTH',
'MAX_FILESIZE_DOWNLOAD',
'MAX_FILESIZE_UPLOAD',
'MAX_MESSAGES_PER_MINUTE_PER_GROUP',
'MAX_MESSAGES_PER_SECOND',
'MAX_MESSAGES_PER_SECOND_PER_CHAT',
'MAX_MESSAGE_LENGTH',
'MaskPosition',
'Message',
'MessageEntity',
'MessageId',
'OrderInfo',
'ParseMode',
'PassportData',
'PassportElementError',
'PassportElementErrorDataField',
'PassportElementErrorFile',
'PassportElementErrorFiles',
'PassportElementErrorFrontSide',
'PassportElementErrorReverseSide',
'PassportElementErrorSelfie',
'PassportElementErrorTranslationFile',
'PassportElementErrorTranslationFiles',
'PassportElementErrorUnspecified',
'PassportFile',
'PersonalDetails',
'PhotoSize',
'ReplyKeyboardRemove',
'Poll',
'PollAnswer',
'PollOption',
'PreCheckoutQuery',
'ProximityAlertTriggered',
'ReplyKeyboardMarkup',
'ReplyKeyboardRemove',
'ReplyMarkup',
'ResidentialAddress',
'SUPPORTED_WEBHOOK_PORTS',
'SecureData',
'SecureValue',
'ShippingAddress',
'ShippingOption',
'ShippingQuery',
'Sticker',
'StickerSet',
'SuccessfulPayment',
'TelegramDecryptionError',
'TelegramError',
'TelegramObject',
'Update',
@ -213,65 +270,7 @@ __all__ = [
'UserProfilePhotos',
'Venue',
'Video',
'Voice',
'MAX_MESSAGE_LENGTH',
'MAX_CAPTION_LENGTH',
'SUPPORTED_WEBHOOK_PORTS',
'MAX_FILESIZE_DOWNLOAD',
'MAX_FILESIZE_UPLOAD',
'MAX_MESSAGES_PER_SECOND_PER_CHAT',
'MAX_MESSAGES_PER_SECOND',
'MAX_MESSAGES_PER_MINUTE_PER_GROUP',
'WebhookInfo',
'Animation',
'Game',
'GameHighScore',
'VideoNote',
'LabeledPrice',
'SuccessfulPayment',
'ShippingOption',
'ShippingAddress',
'PreCheckoutQuery',
'OrderInfo',
'Invoice',
'ShippingQuery',
'ChatPhoto',
'StickerSet',
'MaskPosition',
'CallbackGame',
'InputMedia',
'InputMediaPhoto',
'InputMediaVideo',
'PassportElementError',
'PassportElementErrorFile',
'PassportElementErrorReverseSide',
'PassportElementErrorFrontSide',
'PassportElementErrorFiles',
'PassportElementErrorDataField',
'PassportElementErrorFile',
'Credentials',
'DataCredentials',
'SecureData',
'FileCredentials',
'IdDocumentData',
'PersonalDetails',
'ResidentialAddress',
'InputMediaVideo',
'InputMediaAnimation',
'InputMediaAudio',
'InputMediaDocument',
'TelegramDecryptionError',
'PassportElementErrorSelfie',
'PassportElementErrorTranslationFile',
'PassportElementErrorTranslationFiles',
'PassportElementErrorUnspecified',
'Poll',
'PollOption',
'PollAnswer',
'LoginUrl',
'KeyboardButton',
'KeyboardButtonPollType',
'Dice',
'BotCommand',
'MessageId',
]
'Voice',
'WebhookInfo',
)

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, List, Optional, Union, Tuple, ClassVar
from telegram import Message, TelegramObject, User, Location, ReplyMarkup, constants
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput, DVInput
if TYPE_CHECKING:
from telegram import (
@ -128,7 +129,7 @@ class CallbackQuery(TelegramObject):
show_alert: bool = False,
url: str = None,
cache_time: int = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -155,10 +156,10 @@ class CallbackQuery(TelegramObject):
def edit_message_text(
self,
text: str,
parse_mode: str = None,
disable_web_page_preview: bool = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> Union[Message, bool]:
@ -206,8 +207,8 @@ class CallbackQuery(TelegramObject):
self,
caption: str = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
parse_mode: str = None,
timeout: ODVInput[float] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> Union[Message, bool]:
@ -253,7 +254,7 @@ class CallbackQuery(TelegramObject):
def edit_message_reply_markup(
self,
reply_markup: Optional['InlineKeyboardMarkup'] = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
@ -300,7 +301,7 @@ class CallbackQuery(TelegramObject):
self,
media: 'InputMedia' = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
@ -343,7 +344,7 @@ class CallbackQuery(TelegramObject):
longitude: float = None,
location: Location = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
horizontal_accuracy: float = None,
heading: int = None,
@ -398,7 +399,7 @@ class CallbackQuery(TelegramObject):
def stop_message_live_location(
self,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
@ -441,7 +442,7 @@ class CallbackQuery(TelegramObject):
score: int,
force: bool = None,
disable_edit_message: bool = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
@ -485,7 +486,7 @@ class CallbackQuery(TelegramObject):
def get_game_high_scores(
self,
user_id: Union[int, str],
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> List['GameHighScore']:
"""Shortcut for either::
@ -521,7 +522,7 @@ class CallbackQuery(TelegramObject):
def delete_message(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -542,8 +543,8 @@ class CallbackQuery(TelegramObject):
def pin_message(
self,
disable_notification: bool = None,
timeout: float = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -568,7 +569,7 @@ class CallbackQuery(TelegramObject):
def unpin_message(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -594,13 +595,13 @@ class CallbackQuery(TelegramObject):
self,
chat_id: Union[int, str],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::

View file

@ -22,11 +22,11 @@ from datetime import datetime
from typing import TYPE_CHECKING, List, Optional, ClassVar, Union, Tuple, Any
from telegram import ChatPhoto, TelegramObject, constants
from telegram.utils.types import JSONDict, FileInput
from telegram.utils.types import JSONDict, FileInput, ODVInput, DVInput
from .chatpermissions import ChatPermissions
from .chatlocation import ChatLocation
from .utils.helpers import DefaultValue, DEFAULT_NONE
from .utils.helpers import DEFAULT_NONE, DEFAULT_20
if TYPE_CHECKING:
from telegram import (
@ -231,7 +231,7 @@ class Chat(TelegramObject):
return cls(bot=bot, **data)
def leave(self, timeout: float = None, api_kwargs: JSONDict = None) -> bool:
def leave(self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None) -> bool:
"""Shortcut for::
bot.leave_chat(update.effective_chat.id, *args, **kwargs)
@ -249,7 +249,7 @@ class Chat(TelegramObject):
)
def get_administrators(
self, timeout: float = None, api_kwargs: JSONDict = None
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> List['ChatMember']:
"""Shortcut for::
@ -271,7 +271,9 @@ class Chat(TelegramObject):
api_kwargs=api_kwargs,
)
def get_members_count(self, timeout: float = None, api_kwargs: JSONDict = None) -> int:
def get_members_count(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> int:
"""Shortcut for::
bot.get_chat_members_count(update.effective_chat.id, *args, **kwargs)
@ -292,7 +294,7 @@ class Chat(TelegramObject):
def get_member(
self,
user_id: Union[str, int],
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'ChatMember':
"""Shortcut for::
@ -315,7 +317,7 @@ class Chat(TelegramObject):
def kick_member(
self,
user_id: Union[str, int],
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
until_date: Union[int, datetime] = None,
api_kwargs: JSONDict = None,
) -> bool:
@ -346,7 +348,7 @@ class Chat(TelegramObject):
def unban_member(
self,
user_id: Union[str, int],
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
only_if_banned: bool = None,
) -> bool:
@ -379,7 +381,7 @@ class Chat(TelegramObject):
can_restrict_members: bool = None,
can_pin_messages: bool = None,
can_promote_members: bool = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
is_anonymous: bool = None,
) -> bool:
@ -417,7 +419,7 @@ class Chat(TelegramObject):
user_id: Union[str, int],
permissions: ChatPermissions,
until_date: Union[int, datetime] = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -445,7 +447,7 @@ class Chat(TelegramObject):
def set_permissions(
self,
permissions: ChatPermissions,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -470,7 +472,7 @@ class Chat(TelegramObject):
self,
user_id: Union[int, str],
custom_title: str,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -495,8 +497,8 @@ class Chat(TelegramObject):
def pin_message(
self,
message_id: Union[str, int],
disable_notification: bool = None,
timeout: float = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -522,7 +524,7 @@ class Chat(TelegramObject):
def unpin_message(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
message_id: Union[str, int] = None,
) -> bool:
@ -548,7 +550,7 @@ class Chat(TelegramObject):
def unpin_all_messages(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -573,14 +575,14 @@ class Chat(TelegramObject):
def send_message(
self,
text: str,
parse_mode: str = None,
disable_web_page_preview: bool = None,
disable_notification: bool = False,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> 'Message':
"""Shortcut for::
@ -612,11 +614,11 @@ class Chat(TelegramObject):
media: List[
Union['InputMediaAudio', 'InputMediaDocument', 'InputMediaPhoto', 'InputMediaVideo']
],
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> List['Message']:
"""Shortcut for::
@ -641,7 +643,7 @@ class Chat(TelegramObject):
def send_chat_action(
self,
action: str,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -668,13 +670,13 @@ class Chat(TelegramObject):
self,
photo: Union[FileInput, 'PhotoSize'],
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -708,14 +710,14 @@ class Chat(TelegramObject):
phone_number: str = None,
first_name: str = None,
last_name: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
contact: 'Contact' = None,
vcard: str = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -749,14 +751,14 @@ class Chat(TelegramObject):
performer: str = None,
title: str = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -794,15 +796,15 @@ class Chat(TelegramObject):
document: Union[FileInput, 'Document'],
filename: str = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
disable_content_type_detection: bool = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> 'Message':
"""Shortcut for::
@ -834,13 +836,13 @@ class Chat(TelegramObject):
def send_dice(
self,
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
emoji: str = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -866,12 +868,12 @@ class Chat(TelegramObject):
def send_game(
self,
game_short_name: str,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -912,15 +914,15 @@ class Chat(TelegramObject):
need_email: bool = None,
need_shipping_address: bool = None,
is_flexible: bool = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'InlineKeyboardMarkup' = None,
provider_data: Union[str, object] = None,
send_phone_number_to_provider: bool = None,
send_email_to_provider: bool = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -965,17 +967,17 @@ class Chat(TelegramObject):
self,
latitude: float = None,
longitude: float = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
location: 'Location' = None,
live_period: int = None,
api_kwargs: JSONDict = None,
horizontal_accuracy: float = None,
heading: int = None,
proximity_alert_radius: int = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -1012,13 +1014,13 @@ class Chat(TelegramObject):
height: int = None,
thumb: FileInput = None,
caption: str = None,
parse_mode: str = None,
disable_notification: bool = False,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -1054,12 +1056,12 @@ class Chat(TelegramObject):
def send_sticker(
self,
sticker: Union[FileInput, 'Sticker'],
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -1089,16 +1091,16 @@ class Chat(TelegramObject):
title: str = None,
address: str = None,
foursquare_id: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
venue: 'Venue' = None,
foursquare_type: str = None,
api_kwargs: JSONDict = None,
google_place_id: str = None,
google_place_type: str = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -1134,17 +1136,17 @@ class Chat(TelegramObject):
video: Union[FileInput, 'Video'],
duration: int = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
width: int = None,
height: int = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
supports_streaming: bool = None,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -1183,13 +1185,13 @@ class Chat(TelegramObject):
video_note: Union[FileInput, 'VideoNote'],
duration: int = None,
length: int = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: str = None,
) -> 'Message':
"""Shortcut for::
@ -1222,13 +1224,13 @@ class Chat(TelegramObject):
voice: Union[FileInput, 'Voice'],
duration: int = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -1268,16 +1270,16 @@ class Chat(TelegramObject):
allows_multiple_answers: bool = False,
correct_option_id: int = None,
is_closed: bool = None,
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
explanation: str = None,
explanation_parse_mode: Union[str, DefaultValue, None] = DEFAULT_NONE,
explanation_parse_mode: ODVInput[str] = DEFAULT_NONE,
open_period: int = None,
close_date: Union[int, datetime] = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
explanation_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> 'Message':
"""Shortcut for::
@ -1317,13 +1319,13 @@ class Chat(TelegramObject):
from_chat_id: Union[str, int],
message_id: Union[str, int],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::
@ -1356,13 +1358,13 @@ class Chat(TelegramObject):
chat_id: Union[int, str],
message_id: Union[str, int],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::

View file

@ -291,7 +291,7 @@ class BasePersistence(ABC):
@abstractmethod
def get_user_data(self) -> DefaultDict[int, Dict[object, object]]:
""" "Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
"""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the ``user_data`` if stored, or an empty
``defaultdict(dict)``.
@ -301,7 +301,7 @@ class BasePersistence(ABC):
@abstractmethod
def get_chat_data(self) -> DefaultDict[int, Dict[object, object]]:
""" "Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
"""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the ``chat_data`` if stored, or an empty
``defaultdict(dict)``.
@ -311,7 +311,7 @@ class BasePersistence(ABC):
@abstractmethod
def get_bot_data(self) -> Dict[object, object]:
""" "Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
"""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the ``bot_data`` if stored, or an empty
:obj:`dict`.
@ -321,7 +321,7 @@ class BasePersistence(ABC):
@abstractmethod
def get_conversations(self, name: str) -> ConversationDict:
""" "Will be called by :class:`telegram.ext.Dispatcher` when a
"""Will be called by :class:`telegram.ext.Dispatcher` when a
:class:`telegram.ext.ConversationHandler` is added if
:attr:`telegram.ext.ConversationHandler.persistent` is :obj:`True`.
It should return the conversations for the handler with `name` or an empty :obj:`dict`

View file

@ -118,7 +118,7 @@ class CallbackContext:
@bot_data.setter
def bot_data(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to bot_data, see " "https://git.io/fjxKe"
"You can not assign a new value to bot_data, see https://git.io/Jt6ic"
)
@property
@ -128,7 +128,7 @@ class CallbackContext:
@chat_data.setter
def chat_data(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to chat_data, see " "https://git.io/fjxKe"
"You can not assign a new value to chat_data, see https://git.io/Jt6ic"
)
@property
@ -138,7 +138,7 @@ class CallbackContext:
@user_data.setter
def user_data(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to user_data, see " "https://git.io/fjxKe"
"You can not assign a new value to user_data, see https://git.io/Jt6ic"
)
@classmethod

View file

@ -18,11 +18,12 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=R0201, E0401
"""This module contains the class Defaults, which allows to pass default values to Updater."""
from typing import NoReturn, Optional, Union
from typing import NoReturn, Optional, Dict, Any
import pytz
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
class Defaults:
@ -47,6 +48,9 @@ class Defaults:
appearing throughout PTB, i.e. if a timezone naive date(time) object is passed
somewhere, it will be assumed to be in ``tzinfo``. Must be a timezone provided by the
``pytz`` module. Defaults to UTC.
Note:
Will *not* be used for :meth:`telegram.Bot.get_updates`!
run_async (:obj:`bool`, optional): Default setting for the ``run_async`` parameter of
handlers and error handlers registered through :meth:`Dispatcher.add_handler` and
:meth:`Dispatcher.add_error_handler`. Defaults to :obj:`False`.
@ -54,6 +58,8 @@ class Defaults:
Attributes:
parse_mode (:obj:`str`): Optional. Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or URLs in your bot's message.
explanation_parse_mode (:obj:`str`): Optional. Alias for :attr:`parse_mode`, used for
the corresponding parameter of :meth:`telegram.Bot.send_poll`.
disable_notification (:obj:`bool`): Optional. Sends the message silently. Users will
receive a notification with no sound.
disable_web_page_preview (:obj:`bool`): Optional. Disables link previews for links in this
@ -80,7 +86,7 @@ class Defaults:
disable_web_page_preview: bool = None,
# Timeout needs special treatment, since the bot methods have two different
# default values for timeout (None and 20s)
timeout: Union[float, DefaultValue] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
quote: bool = None,
tzinfo: pytz.BaseTzInfo = pytz.utc,
run_async: bool = False,
@ -95,6 +101,26 @@ class Defaults:
self._tzinfo = tzinfo
self._run_async = run_async
# Gather all defaults that actually have a default value
self._api_defaults = {}
for kwarg in (
'parse_mode',
'explanation_parse_mode',
'disable_notification',
'disable_web_page_preview',
'allow_sending_without_reply',
):
value = getattr(self, kwarg)
if value not in [None, DEFAULT_NONE]:
self._api_defaults[kwarg] = value
# Special casing, as None is a valid default value
if self.timeout != DEFAULT_NONE:
self._api_defaults['timeout'] = self.timeout
@property
def api_defaults(self) -> Dict[str, Any]:
return self._api_defaults
@property
def parse_mode(self) -> Optional[str]:
return self._parse_mode
@ -106,6 +132,17 @@ class Defaults:
"not have any effect."
)
@property
def explanation_parse_mode(self) -> Optional[str]:
return self._parse_mode
@explanation_parse_mode.setter
def explanation_parse_mode(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
)
@property
def disable_notification(self) -> Optional[bool]:
return self._disable_notification
@ -140,7 +177,7 @@ class Defaults:
)
@property
def timeout(self) -> Union[float, DefaultValue]:
def timeout(self) -> ODVInput[float]:
return self._timeout
@timeout.setter

View file

@ -91,7 +91,7 @@ class BaseFilter(ABC):
If you want to create your own filters create a class inheriting from either
:class:`MessageFilter` or :class:`UpdateFilter` and implement a :meth:``filter`` method that
:class:`MessageFilter` or :class:`UpdateFilter` and implement a :meth:`filter` method that
returns a boolean: :obj:`True` if the message should be
handled, :obj:`False` otherwise.
Note that the filters work only as class instances, not
@ -148,7 +148,8 @@ class MessageFilter(BaseFilter, ABC):
"""Base class for all Message Filters. In contrast to :class:`UpdateFilter`, the object passed
to :meth:`filter` is ``update.effective_message``.
Please see :class:`telegram.ext.BaseFilter` for details on how to create custom filters.
Please see :class:`telegram.ext.filters.BaseFilter` for details on how to create custom
filters.
Attributes:
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
@ -176,11 +177,12 @@ class MessageFilter(BaseFilter, ABC):
class UpdateFilter(BaseFilter, ABC):
"""Base class for all Update Filters. In contrast to :class:`UpdateFilter`, the object
"""Base class for all Update Filters. In contrast to :class:`MessageFilter`, the object
passed to :meth:`filter` is ``update``, which allows to create filters like
:attr:`Filters.update.edited_message`.
Please see :class:`telegram.ext.BaseFilter` for details on how to create custom filters.
Please see :class:`telegram.ext.filters.BaseFilter` for details on how to create custom
filters.
Attributes:
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
@ -316,7 +318,7 @@ class MergedFilter(UpdateFilter):
class XORFilter(UpdateFilter):
"""Convenience filter acting as wrapper for :class:`MergedFilter` representing the an XOR gate
for two filters
for two filters.
Args:
base_filter: Filter 1 of the merged filter.
@ -1413,7 +1415,8 @@ officedocument.wordprocessingml.document")``.
user_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which user ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through. Leading '@'s in usernames will be discarded.
Which username(s) to allow through. Leading ``'@'`` s in usernames will be
discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`user_ids` and :attr:`usernames`. Defaults to :obj:`False`
@ -1422,8 +1425,8 @@ officedocument.wordprocessingml.document")``.
Attributes:
user_ids(set(:obj:`int`), optional): Which user ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading '@') to allow
through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading ``'@'``) to
allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`user_ids` and :attr:`usernames`.
@ -1456,7 +1459,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@ -1477,7 +1480,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@ -1511,7 +1514,8 @@ officedocument.wordprocessingml.document")``.
bot_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which bot ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through. Leading '@'s in usernames will be discarded.
Which username(s) to allow through. Leading ``'@'`` s in usernames will be
discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`bot_ids` and :attr:`usernames`. Defaults to :obj:`False`
@ -1520,8 +1524,8 @@ officedocument.wordprocessingml.document")``.
Attributes:
bot_ids(set(:obj:`int`), optional): Which bot ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading '@') to allow
through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading ``'@'``) to
allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no bot
is specified in :attr:`bot_ids` and :attr:`usernames`.
@ -1554,7 +1558,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@ -1576,7 +1580,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@ -1610,7 +1614,7 @@ officedocument.wordprocessingml.document")``.
Which chat ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no chat
is specified in :attr:`chat_ids` and :attr:`usernames`. Defaults to :obj:`False`
@ -1619,8 +1623,8 @@ officedocument.wordprocessingml.document")``.
Attributes:
chat_ids(set(:obj:`int`), optional): Which chat ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading '@') to allow
through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading ``'@'``) to
allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no chat
is specified in :attr:`chat_ids` and :attr:`usernames`.
@ -1636,7 +1640,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@ -1657,7 +1661,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@ -1700,7 +1704,7 @@ officedocument.wordprocessingml.document")``.
Which sender chat chat ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no sender
chat is specified in :attr:`chat_ids` and :attr:`usernames`. Defaults to
:obj:`False`
@ -1711,7 +1715,7 @@ officedocument.wordprocessingml.document")``.
Attributes:
chat_ids(set(:obj:`int`), optional): Which sender chat chat ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which sender chat username(s) (without leading
'@') to allow through.
``'@'``) to allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no sender
chat is specified in :attr:`chat_ids` and :attr:`usernames`.
super_group: Messages whose sender chat is a super group.
@ -1735,7 +1739,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@ -1756,7 +1760,7 @@ officedocument.wordprocessingml.document")``.
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat username(s) to disallow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)

View file

@ -24,9 +24,11 @@ import functools
import queue as q
import threading
import time
import warnings
from typing import TYPE_CHECKING, Callable, List, NoReturn
from telegram.ext.utils.promise import Promise
from telegram.utils.deprecate import TelegramDeprecationWarning
if TYPE_CHECKING:
from telegram import Bot
@ -44,6 +46,10 @@ class DelayQueue(threading.Thread):
Processes callbacks from queue with specified throughput limits. Creates a separate thread to
process callbacks with delays.
.. deprecated:: 13.3
:class:`telegram.ext.DelayQueue` in its current form is deprecated and will be reinvented
in a future release. See `this thread <https://git.io/JtDbF>`_ for a list of known bugs.
Args:
queue (:obj:`Queue`, optional): Used to pass callbacks to thread. Creates ``Queue``
implicitly if not provided.
@ -82,6 +88,12 @@ class DelayQueue(threading.Thread):
autostart: bool = True,
name: str = None,
):
warnings.warn(
'DelayQueue in its current form is deprecated and will be reinvented in a future '
'release. See https://git.io/JtDbF for a list of known bugs.',
category=TelegramDeprecationWarning,
)
self._queue = queue if queue is not None else q.Queue()
self.burst_limit = burst_limit
self.time_limit = time_limit_ms / 1000
@ -182,6 +194,10 @@ class MessageQueue:
Callables are processed through *group* ``DelayQueue``, then through *all* ``DelayQueue`` for
group-type messages. For non-group messages, only the *all* ``DelayQueue`` is used.
.. deprecated:: 13.3
:class:`telegram.ext.MessageQueue` in its current form is deprecated and will be reinvented
in a future release. See `this thread <https://git.io/JtDbF>`_ for a list of known bugs.
Args:
all_burst_limit (:obj:`int`, optional): Number of maximum *all-type* callbacks to process
per time-window defined by :attr:`all_time_limit_ms`. Defaults to 30.
@ -210,6 +226,12 @@ class MessageQueue:
exc_route: Callable[[Exception], None] = None,
autostart: bool = True,
):
warnings.warn(
'MessageQueue in its current form is deprecated and will be reinvented in a future '
'release. See https://git.io/JtDbF for a list of known bugs.',
category=TelegramDeprecationWarning,
)
# create according delay queues, use composition
self._all_delayq = DelayQueue(
burst_limit=all_burst_limit,

View file

@ -20,7 +20,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -104,7 +105,9 @@ class Animation(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -108,7 +109,9 @@ class Audio(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -20,7 +20,8 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -85,7 +86,9 @@ class ChatPhoto(TelegramObject):
self.big_file_unique_id,
)
def get_small_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_small_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file` for getting the
small (160x160) chat photo
@ -102,7 +105,9 @@ class ChatPhoto(TelegramObject):
file_id=self.small_file_id, timeout=timeout, api_kwargs=api_kwargs
)
def get_big_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_big_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file` for getting the
big (640x640) chat photo

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -95,7 +96,9 @@ class Document(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -30,8 +30,8 @@ from telegram import (
Video,
MessageEntity,
)
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue, parse_file_input
from telegram.utils.types import FileInput, JSONDict
from telegram.utils.helpers import DEFAULT_NONE, parse_file_input
from telegram.utils.types import FileInput, JSONDict, ODVInput
class InputMedia(TelegramObject):
@ -117,7 +117,7 @@ class InputMediaAnimation(InputMedia):
media: Union[FileInput, Animation],
thumb: FileInput = None,
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
width: int = None,
height: int = None,
duration: int = None,
@ -188,7 +188,7 @@ class InputMediaPhoto(InputMedia):
self,
media: Union[FileInput, PhotoSize],
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
@ -272,7 +272,7 @@ class InputMediaVideo(InputMedia):
height: int = None,
duration: int = None,
supports_streaming: bool = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
@ -368,7 +368,7 @@ class InputMediaAudio(InputMedia):
media: Union[FileInput, Audio],
thumb: FileInput = None,
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
duration: int = None,
performer: str = None,
title: str = None,
@ -456,7 +456,7 @@ class InputMediaDocument(InputMedia):
media: Union[FileInput, Document],
thumb: FileInput = None,
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_content_type_detection: bool = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -78,7 +79,9 @@ class PhotoSize(TelegramObject):
self._id_attrs = (self.file_unique_id,)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, List, Optional, ClassVar
from telegram import PhotoSize, TelegramObject, constants
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -115,7 +116,9 @@ class Sticker(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -105,7 +106,9 @@ class Video(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Optional, Any
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -94,7 +95,9 @@ class VideoNote(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@ -78,7 +79,9 @@ class Voice(TelegramObject):
self._id_attrs = (self.file_unique_id,)
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.

View file

@ -22,7 +22,8 @@
from typing import TYPE_CHECKING, Any, Optional, List, Union, Callable, ClassVar
from telegram import Location, TelegramObject, User, constants
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, InlineQueryResult
@ -103,7 +104,7 @@ class InlineQuery(TelegramObject):
next_offset: str = None,
switch_pm_text: str = None,
switch_pm_parameter: str = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
current_offset: str = None,
api_kwargs: JSONDict = None,
auto_pagination: bool = False,

View file

@ -49,14 +49,6 @@ class InlineQueryResult(TelegramObject):
self._id_attrs = (self.id,)
@property
def _has_parse_mode(self) -> bool:
return hasattr(self, 'parse_mode')
@property
def _has_input_message_content(self) -> bool:
return hasattr(self, 'input_message_content')
def to_dict(self) -> JSONDict:
data = super().to_dict()

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -83,7 +84,7 @@ class InlineQueryResultAudio(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -74,7 +75,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -22,7 +22,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -83,7 +84,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -80,7 +81,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -80,7 +81,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -22,7 +22,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -84,7 +85,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -83,7 +84,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -77,7 +78,7 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -97,7 +98,7 @@ class InlineQueryResultDocument(InlineQueryResult):
thumb_url: str = None,
thumb_width: int = None,
thumb_height: int = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -22,7 +22,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -97,7 +98,7 @@ class InlineQueryResultGif(InlineQueryResult):
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
gif_duration: int = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb_mime_type: str = None,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -96,7 +97,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
mpeg4_duration: int = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb_mime_type: str = None,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -93,7 +94,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -105,7 +106,7 @@ class InlineQueryResultVideo(InlineQueryResult):
description: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Union, Tuple, List
from telegram import InlineQueryResult, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
if TYPE_CHECKING:
from telegram import InputMessageContent, ReplyMarkup
@ -81,7 +82,7 @@ class InlineQueryResultVoice(InlineQueryResult):
caption: str = None,
reply_markup: 'ReplyMarkup' = None,
input_message_content: 'InputMessageContent' = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -29,11 +29,3 @@ class InputMessageContent(TelegramObject):
:class:`telegram.InputVenueMessageContent` for more details.
"""
@property
def _has_parse_mode(self) -> bool:
return hasattr(self, 'parse_mode')
@property
def _has_disable_web_page_preview(self) -> bool:
return hasattr(self, 'disable_web_page_preview')

View file

@ -21,8 +21,8 @@
from typing import Any, Union, Tuple, List
from telegram import InputMessageContent, MessageEntity
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
class InputTextMessageContent(InputMessageContent):
@ -62,8 +62,8 @@ class InputTextMessageContent(InputMessageContent):
def __init__(
self,
message_text: str,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
disable_web_page_preview: Union[bool, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
entities: Union[Tuple[MessageEntity, ...], List[MessageEntity]] = None,
**_kwargs: Any,
):

View file

@ -55,9 +55,9 @@ from telegram.utils.helpers import (
from_timestamp,
to_timestamp,
DEFAULT_NONE,
DefaultValue,
DEFAULT_20,
)
from telegram.utils.types import JSONDict, FileInput
from telegram.utils.types import JSONDict, FileInput, ODVInput, DVInput
if TYPE_CHECKING:
from telegram import (
@ -605,14 +605,14 @@ class Message(TelegramObject):
def reply_text(
self,
text: str,
parse_mode: str = None,
disable_web_page_preview: bool = None,
disable_notification: bool = False,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
quote: bool = None,
) -> 'Message':
@ -650,13 +650,13 @@ class Message(TelegramObject):
def reply_markdown(
self,
text: str,
disable_web_page_preview: bool = None,
disable_notification: bool = False,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
quote: bool = None,
) -> 'Message':
@ -704,13 +704,13 @@ class Message(TelegramObject):
def reply_markdown_v2(
self,
text: str,
disable_web_page_preview: bool = None,
disable_notification: bool = False,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
quote: bool = None,
) -> 'Message':
@ -754,13 +754,13 @@ class Message(TelegramObject):
def reply_html(
self,
text: str,
disable_web_page_preview: bool = None,
disable_notification: bool = False,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
quote: bool = None,
) -> 'Message':
@ -806,11 +806,11 @@ class Message(TelegramObject):
media: List[
Union['InputMediaAudio', 'InputMediaDocument', 'InputMediaPhoto', 'InputMediaVideo']
],
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> List['Message']:
"""Shortcut for::
@ -846,13 +846,13 @@ class Message(TelegramObject):
self,
photo: Union[FileInput, 'PhotoSize'],
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
quote: bool = None,
@ -896,14 +896,14 @@ class Message(TelegramObject):
performer: str = None,
title: str = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
quote: bool = None,
@ -949,15 +949,15 @@ class Message(TelegramObject):
document: Union[FileInput, 'Document'],
filename: str = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
disable_content_type_detection: bool = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
quote: bool = None,
) -> 'Message':
@ -1003,13 +1003,13 @@ class Message(TelegramObject):
height: int = None,
thumb: FileInput = None,
caption: str = None,
parse_mode: str = None,
disable_notification: bool = False,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
quote: bool = None,
@ -1053,12 +1053,12 @@ class Message(TelegramObject):
def reply_sticker(
self,
sticker: Union[FileInput, 'Sticker'],
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1094,17 +1094,17 @@ class Message(TelegramObject):
video: Union[FileInput, 'Video'],
duration: int = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
width: int = None,
height: int = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
supports_streaming: bool = None,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
quote: bool = None,
@ -1151,13 +1151,13 @@ class Message(TelegramObject):
video_note: Union[FileInput, 'VideoNote'],
duration: int = None,
length: int = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: str = None,
quote: bool = None,
) -> 'Message':
@ -1198,13 +1198,13 @@ class Message(TelegramObject):
voice: Union[FileInput, 'Voice'],
duration: int = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
quote: bool = None,
@ -1246,17 +1246,17 @@ class Message(TelegramObject):
self,
latitude: float = None,
longitude: float = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
location: Location = None,
live_period: int = None,
api_kwargs: JSONDict = None,
horizontal_accuracy: float = None,
heading: int = None,
proximity_alert_radius: int = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1300,16 +1300,16 @@ class Message(TelegramObject):
title: str = None,
address: str = None,
foursquare_id: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
venue: Venue = None,
foursquare_type: str = None,
api_kwargs: JSONDict = None,
google_place_id: str = None,
google_place_type: str = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1353,14 +1353,14 @@ class Message(TelegramObject):
phone_number: str = None,
first_name: str = None,
last_name: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
contact: Contact = None,
vcard: str = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1404,16 +1404,16 @@ class Message(TelegramObject):
allows_multiple_answers: bool = False,
correct_option_id: int = None,
is_closed: bool = None,
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
explanation: str = None,
explanation_parse_mode: Union[str, DefaultValue, None] = DEFAULT_NONE,
explanation_parse_mode: ODVInput[str] = DEFAULT_NONE,
open_period: int = None,
close_date: Union[int, datetime.datetime] = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
explanation_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
quote: bool = None,
) -> 'Message':
@ -1458,13 +1458,13 @@ class Message(TelegramObject):
def reply_dice(
self,
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
emoji: str = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1498,7 +1498,7 @@ class Message(TelegramObject):
def reply_chat_action(
self,
action: str,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -1523,12 +1523,12 @@ class Message(TelegramObject):
def reply_game(
self,
game_short_name: str,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1579,15 +1579,15 @@ class Message(TelegramObject):
need_email: bool = None,
need_shipping_address: bool = None,
is_flexible: bool = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'InlineKeyboardMarkup' = None,
provider_data: Union[str, object] = None,
send_phone_number_to_provider: bool = None,
send_email_to_provider: bool = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
quote: bool = None,
) -> 'Message':
"""Shortcut for::
@ -1641,8 +1641,8 @@ class Message(TelegramObject):
def forward(
self,
chat_id: Union[int, str],
disable_notification: bool = False,
timeout: float = None,
disable_notification: DVInput[bool] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'Message':
"""Shortcut for::
@ -1672,13 +1672,13 @@ class Message(TelegramObject):
self,
chat_id: Union[int, str],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::
@ -1715,13 +1715,13 @@ class Message(TelegramObject):
from_chat_id: Union[str, int],
message_id: Union[str, int],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: ReplyMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
quote: bool = None,
) -> 'MessageId':
@ -1766,10 +1766,10 @@ class Message(TelegramObject):
def edit_text(
self,
text: str,
parse_mode: str = None,
disable_web_page_preview: bool = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
reply_markup: InlineKeyboardMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> Union['Message', bool]:
@ -1809,8 +1809,8 @@ class Message(TelegramObject):
self,
caption: str = None,
reply_markup: InlineKeyboardMarkup = None,
timeout: float = None,
parse_mode: str = None,
timeout: ODVInput[float] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> Union['Message', bool]:
@ -1850,7 +1850,7 @@ class Message(TelegramObject):
self,
media: 'InputMedia' = None,
reply_markup: InlineKeyboardMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union['Message', bool]:
"""Shortcut for::
@ -1886,7 +1886,7 @@ class Message(TelegramObject):
def edit_reply_markup(
self,
reply_markup: Optional['InlineKeyboardMarkup'] = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union['Message', bool]:
"""Shortcut for::
@ -1923,7 +1923,7 @@ class Message(TelegramObject):
longitude: float = None,
location: Location = None,
reply_markup: InlineKeyboardMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
horizontal_accuracy: float = None,
heading: int = None,
@ -1966,7 +1966,7 @@ class Message(TelegramObject):
def stop_live_location(
self,
reply_markup: InlineKeyboardMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union['Message', bool]:
"""Shortcut for::
@ -2003,7 +2003,7 @@ class Message(TelegramObject):
score: int,
force: bool = None,
disable_edit_message: bool = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union['Message', bool]:
"""Shortcut for::
@ -2039,7 +2039,7 @@ class Message(TelegramObject):
def get_game_high_scores(
self,
user_id: Union[int, str],
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> List['GameHighScore']:
"""Shortcut for::
@ -2071,7 +2071,7 @@ class Message(TelegramObject):
def delete(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -2097,7 +2097,7 @@ class Message(TelegramObject):
def stop_poll(
self,
reply_markup: InlineKeyboardMarkup = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Poll:
"""Shortcut for::
@ -2124,8 +2124,8 @@ class Message(TelegramObject):
def pin(
self,
disable_notification: bool = None,
timeout: float = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -2151,7 +2151,7 @@ class Message(TelegramObject):
def unpin(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

View file

@ -25,12 +25,21 @@ except ImportError:
from base64 import b64decode
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union, no_type_check
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import CBC
from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512, Hash
try:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import CBC
from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512, Hash
CRYPTO_INSTALLED = True
except ImportError:
default_backend = None
MGF1, OAEP, Cipher, AES, CBC = (None, None, None, None, None) # type: ignore[misc]
SHA1, SHA256, SHA512, Hash = (None, None, None, None) # type: ignore[misc]
CRYPTO_INSTALLED = False
from telegram import TelegramError, TelegramObject
from telegram.utils.types import JSONDict
@ -74,6 +83,11 @@ def decrypt(secret, hash, data):
:obj:`bytes`: The decrypted data as bytes.
"""
if not CRYPTO_INSTALLED:
raise RuntimeError(
'To use Telegram Passports, PTB must be installed via `pip install '
'python-telegram-bot[passport]`.'
)
# Make a SHA512 hash of secret + update
digest = Hash(SHA512(), backend=default_backend())
digest.update(secret + hash)
@ -153,6 +167,11 @@ class EncryptedCredentials(TelegramObject):
private/public key but can also suggest malformed/tampered data.
"""
if self._decrypted_secret is None:
if not CRYPTO_INSTALLED:
raise RuntimeError(
'To use Telegram Passports, PTB must be installed via `pip install '
'python-telegram-bot[passport]`.'
)
# Try decrypting according to step 1 at
# https://core.telegram.org/passport#decrypting-data
# We make sure to base64 decode the secret first.

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, List, Optional
from telegram import TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File, FileCredentials
@ -103,7 +104,9 @@ class PassportFile(TelegramObject):
for i, passport_file in enumerate(data)
]
def get_file(self, timeout: float = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""
Wrapper over :attr:`telegram.Bot.get_file`. Will automatically assign the correct
credentials to the returned :class:`telegram.File` if originating from

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import OrderInfo, TelegramObject, User
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot
@ -106,7 +107,7 @@ class PreCheckoutQuery(TelegramObject):
self,
ok: bool,
error_message: str = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

View file

@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional, List
from telegram import ShippingAddress, TelegramObject, User, ShippingOption
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot
@ -88,7 +89,7 @@ class ShippingQuery(TelegramObject):
ok: bool,
shipping_options: List[ShippingOption] = None,
error_message: str = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::

View file

@ -22,9 +22,13 @@ from datetime import datetime
from typing import TYPE_CHECKING, Any, List, Optional, Union, Tuple
from telegram import TelegramObject, constants
from telegram.utils.helpers import mention_html as util_mention_html, DefaultValue, DEFAULT_NONE
from telegram.utils.helpers import (
mention_html as util_mention_html,
DEFAULT_NONE,
DEFAULT_20,
)
from telegram.utils.helpers import mention_markdown as util_mention_markdown
from telegram.utils.types import JSONDict, FileInput
from telegram.utils.types import JSONDict, FileInput, ODVInput, DVInput
if TYPE_CHECKING:
from telegram import (
@ -151,7 +155,7 @@ class User(TelegramObject):
self,
offset: int = None,
limit: int = 100,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Optional['UserProfilePhotos']:
"""
@ -218,8 +222,8 @@ class User(TelegramObject):
def pin_message(
self,
message_id: Union[str, int],
disable_notification: bool = None,
timeout: float = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -244,7 +248,7 @@ class User(TelegramObject):
def unpin_message(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
message_id: Union[str, int] = None,
) -> bool:
@ -269,7 +273,7 @@ class User(TelegramObject):
def unpin_all_messages(
self,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -294,14 +298,14 @@ class User(TelegramObject):
def send_message(
self,
text: str,
parse_mode: str = None,
disable_web_page_preview: bool = None,
disable_notification: bool = False,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> 'Message':
"""Shortcut for::
@ -332,13 +336,13 @@ class User(TelegramObject):
self,
photo: Union[FileInput, 'PhotoSize'],
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -372,11 +376,11 @@ class User(TelegramObject):
media: List[
Union['InputMediaAudio', 'InputMediaDocument', 'InputMediaPhoto', 'InputMediaVideo']
],
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> List['Message']:
"""Shortcut for::
@ -405,14 +409,14 @@ class User(TelegramObject):
performer: str = None,
title: str = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -448,7 +452,7 @@ class User(TelegramObject):
def send_chat_action(
self,
action: str,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
@ -476,14 +480,14 @@ class User(TelegramObject):
phone_number: str = None,
first_name: str = None,
last_name: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
contact: 'Contact' = None,
vcard: str = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -512,13 +516,13 @@ class User(TelegramObject):
def send_dice(
self,
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
emoji: str = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -546,15 +550,15 @@ class User(TelegramObject):
document: Union[FileInput, 'Document'],
filename: str = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
disable_content_type_detection: bool = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> 'Message':
"""Shortcut for::
@ -587,12 +591,12 @@ class User(TelegramObject):
def send_game(
self,
game_short_name: str,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -633,15 +637,15 @@ class User(TelegramObject):
need_email: bool = None,
need_shipping_address: bool = None,
is_flexible: bool = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'InlineKeyboardMarkup' = None,
provider_data: Union[str, object] = None,
send_phone_number_to_provider: bool = None,
send_email_to_provider: bool = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -686,17 +690,17 @@ class User(TelegramObject):
self,
latitude: float = None,
longitude: float = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
location: 'Location' = None,
live_period: int = None,
api_kwargs: JSONDict = None,
horizontal_accuracy: float = None,
heading: int = None,
proximity_alert_radius: int = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -733,13 +737,13 @@ class User(TelegramObject):
height: int = None,
thumb: FileInput = None,
caption: str = None,
parse_mode: str = None,
disable_notification: bool = False,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -775,12 +779,12 @@ class User(TelegramObject):
def send_sticker(
self,
sticker: Union[FileInput, 'Sticker'],
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -808,17 +812,17 @@ class User(TelegramObject):
video: Union[FileInput, 'Video'],
duration: int = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
width: int = None,
height: int = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
supports_streaming: bool = None,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -859,16 +863,16 @@ class User(TelegramObject):
title: str = None,
address: str = None,
foursquare_id: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
venue: 'Venue' = None,
foursquare_type: str = None,
api_kwargs: JSONDict = None,
google_place_id: str = None,
google_place_type: str = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
) -> 'Message':
"""Shortcut for::
@ -904,13 +908,13 @@ class User(TelegramObject):
video_note: Union[FileInput, 'VideoNote'],
duration: int = None,
length: int = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
timeout: DVInput[float] = DEFAULT_20,
thumb: FileInput = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: str = None,
) -> 'Message':
"""Shortcut for::
@ -943,13 +947,13 @@ class User(TelegramObject):
voice: Union[FileInput, 'Voice'],
duration: int = None,
caption: str = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = 20,
parse_mode: str = None,
timeout: DVInput[float] = DEFAULT_20,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
filename: str = None,
) -> 'Message':
@ -989,16 +993,16 @@ class User(TelegramObject):
allows_multiple_answers: bool = False,
correct_option_id: int = None,
is_closed: bool = None,
disable_notification: bool = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
explanation: str = None,
explanation_parse_mode: Union[str, DefaultValue, None] = DEFAULT_NONE,
explanation_parse_mode: ODVInput[str] = DEFAULT_NONE,
open_period: int = None,
close_date: Union[int, datetime] = None,
api_kwargs: JSONDict = None,
allow_sending_without_reply: bool = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
explanation_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> 'Message':
"""Shortcut for::
@ -1038,13 +1042,13 @@ class User(TelegramObject):
from_chat_id: Union[str, int],
message_id: Union[str, int],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::
@ -1077,13 +1081,13 @@ class User(TelegramObject):
chat_id: Union[int, str],
message_id: Union[str, int],
caption: str = None,
parse_mode: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: bool = False,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: bool = False,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: 'ReplyMarkup' = None,
timeout: float = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::

View file

@ -38,6 +38,9 @@ from typing import (
Type,
cast,
IO,
TypeVar,
Generic,
overload,
)
from telegram.utils.types import JSONDict, FileInput
@ -494,7 +497,11 @@ def decode_user_chat_data_from_json(data: str) -> DefaultDict[int, Dict[object,
return tmp
class DefaultValue:
DVType = TypeVar('DVType', bound=object)
OT = TypeVar('OT', bound=object)
class DefaultValue(Generic[DVType]):
"""Wrapper for immutable default arguments that allows to check, if the default value was set
explicitly. Usage::
@ -531,6 +538,9 @@ class DefaultValue:
if value:
...
``repr(DefaultValue(value))`` returns ``repr(value)`` and ``str(DefaultValue(value))`` returns
``f'DefaultValue({value})'``.
Args:
value (:obj:`obj`): The value of the default argument
@ -539,15 +549,51 @@ class DefaultValue:
"""
def __init__(self, value: object = None):
def __init__(self, value: DVType = None):
self.value = value
def __bool__(self) -> bool:
return bool(self.value)
@overload
@staticmethod
def get_value(obj: 'DefaultValue[OT]') -> OT:
...
@overload
@staticmethod
def get_value(obj: OT) -> OT:
...
@staticmethod
def get_value(obj: Union[OT, 'DefaultValue[OT]']) -> OT:
"""
Shortcut for::
return obj.value if isinstance(obj, DefaultValue) else obj
Args:
obj (:obj:`object`): The object to process
Returns:
Same type as input, or the value of the input: The value
"""
return obj.value if isinstance(obj, DefaultValue) else obj # type: ignore[return-value]
# This is mostly here for readability during debugging
def __str__(self) -> str:
return f'DefaultValue({self.value})'
# This is here to have the default instances nicely rendered in the docs
def __repr__(self) -> str:
return repr(self.value)
DEFAULT_NONE: DefaultValue = DefaultValue(None)
""":class:`DefaultValue`: Default :obj:`None`"""
DEFAULT_FALSE: DefaultValue = DefaultValue(False)
""":class:`DefaultValue`: Default :obj:`False`"""
DEFAULT_20: DefaultValue = DefaultValue(20)
""":class:`DefaultValue`: Default :obj:`20`"""

View file

@ -22,6 +22,7 @@ from typing import IO, TYPE_CHECKING, Any, Dict, List, Optional, Tuple, TypeVar,
if TYPE_CHECKING:
from telegram import InputFile
from telegram.utils.helpers import DefaultValue
FileLike = Union[IO, 'InputFile']
"""Either an open file handler or a :class:`telegram.InputFile`."""
@ -36,6 +37,14 @@ JSONDict = Dict[str, Any]
ConversationDict = Dict[Tuple[int, ...], Optional[object]]
"""Dicts as maintained by the :class:`telegram.ext.ConversationHandler`."""
DVType = TypeVar('DVType')
ODVInput = Optional[Union['DefaultValue[DVType]', DVType]]
"""Generic type for bot method parameters which can have defaults. ``ODVInput[type]`` is the same
as ``Optional[Union[DefaultValue, type]]``."""
DVInput = Union['DefaultValue[DVType]', DVType]
"""Generic type for bot method parameters which can have defaults. ``DVInput[type]`` is the same
as ``Union[DefaultValue, type]``."""
RT = TypeVar("RT")
SLT = Union[RT, List[RT], Tuple[RT, ...]]
"""Single instance or list/tuple of instances."""

View file

@ -18,4 +18,4 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=C0114
__version__ = '13.2'
__version__ = '13.3'

View file

@ -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/].
import datetime
import functools
import inspect
import os
import re
@ -24,7 +25,7 @@ from collections import defaultdict
from queue import Queue
from threading import Thread, Event
from time import sleep
from typing import Callable, List, Dict
from typing import Callable, List, Iterable, Any
import pytest
import pytz
@ -41,11 +42,22 @@ from telegram import (
ShippingQuery,
PreCheckoutQuery,
ChosenInlineResult,
File,
ChatPermissions,
)
from telegram.ext import Dispatcher, JobQueue, Updater, MessageFilter, Defaults, UpdateFilter
from telegram.error import BadRequest
from telegram.utils.helpers import DefaultValue, DEFAULT_NONE
from tests.bots import get_bot
# This is here instead of in setup.cfg due to https://github.com/pytest-dev/pytest/issues/8343
def pytest_runtestloop(session):
session.add_marker(
pytest.mark.filterwarnings('ignore::telegram.utils.deprecate.TelegramDeprecationWarning')
)
GITHUB_ACTION = os.getenv('GITHUB_ACTION', False)
if GITHUB_ACTION:
@ -56,6 +68,14 @@ if GITHUB_ACTION:
PRIVATE_KEY = b"-----BEGIN RSA PRIVATE KEY-----\r\nMIIEowIBAAKCAQEA0AvEbNaOnfIL3GjB8VI4M5IaWe+GcK8eSPHkLkXREIsaddum\r\nwPBm/+w8lFYdnY+O06OEJrsaDtwGdU//8cbGJ/H/9cJH3dh0tNbfszP7nTrQD+88\r\nydlcYHzClaG8G+oTe9uEZSVdDXj5IUqR0y6rDXXb9tC9l+oSz+ShYg6+C4grAb3E\r\nSTv5khZ9Zsi/JEPWStqNdpoNuRh7qEYc3t4B/a5BH7bsQENyJSc8AWrfv+drPAEe\r\njQ8xm1ygzWvJp8yZPwOIYuL+obtANcoVT2G2150Wy6qLC0bD88Bm40GqLbSazueC\r\nRHZRug0B9rMUKvKc4FhG4AlNzBCaKgIcCWEqKwIDAQABAoIBACcIjin9d3Sa3S7V\r\nWM32JyVF3DvTfN3XfU8iUzV7U+ZOswA53eeFM04A/Ly4C4ZsUNfUbg72O8Vd8rg/\r\n8j1ilfsYpHVvphwxaHQlfIMa1bKCPlc/A6C7b2GLBtccKTbzjARJA2YWxIaqk9Nz\r\nMjj1IJK98i80qt29xRnMQ5sqOO3gn2SxTErvNchtBiwOH8NirqERXig8VCY6fr3n\r\nz7ZImPU3G/4qpD0+9ULrt9x/VkjqVvNdK1l7CyAuve3D7ha3jPMfVHFtVH5gqbyp\r\nKotyIHAyD+Ex3FQ1JV+H7DkP0cPctQiss7OiO9Zd9C1G2OrfQz9el7ewAPqOmZtC\r\nKjB3hUECgYEA/4MfKa1cvaCqzd3yUprp1JhvssVkhM1HyucIxB5xmBcVLX2/Kdhn\r\nhiDApZXARK0O9IRpFF6QVeMEX7TzFwB6dfkyIePsGxputA5SPbtBlHOvjZa8omMl\r\nEYfNa8x/mJkvSEpzvkWPascuHJWv1cEypqphu/70DxubWB5UKo/8o6cCgYEA0HFy\r\ncgwPMB//nltHGrmaQZPFT7/Qgl9ErZT3G9S8teWY4o4CXnkdU75tBoKAaJnpSfX3\r\nq8VuRerF45AFhqCKhlG4l51oW7TUH50qE3GM+4ivaH5YZB3biwQ9Wqw+QyNLAh/Q\r\nnS4/Wwb8qC9QuyEgcCju5lsCaPEXZiZqtPVxZd0CgYEAshBG31yZjO0zG1TZUwfy\r\nfN3euc8mRgZpSdXIHiS5NSyg7Zr8ZcUSID8jAkJiQ3n3OiAsuq1MGQ6kNa582kLT\r\nFPQdI9Ea8ahyDbkNR0gAY9xbM2kg/Gnro1PorH9PTKE0ekSodKk1UUyNrg4DBAwn\r\nqE6E3ebHXt/2WmqIbUD653ECgYBQCC8EAQNX3AFegPd1GGxU33Lz4tchJ4kMCNU0\r\nN2NZh9VCr3nTYjdTbxsXU8YP44CCKFG2/zAO4kymyiaFAWEOn5P7irGF/JExrjt4\r\nibGy5lFLEq/HiPtBjhgsl1O0nXlwUFzd7OLghXc+8CPUJaz5w42unqT3PBJa40c3\r\nQcIPdQKBgBnSb7BcDAAQ/Qx9juo/RKpvhyeqlnp0GzPSQjvtWi9dQRIu9Pe7luHc\r\nm1Img1EO1OyE3dis/rLaDsAa2AKu1Yx6h85EmNjavBqP9wqmFa0NIQQH8fvzKY3/\r\nP8IHY6009aoamLqYaexvrkHVq7fFKiI6k8myMJ6qblVNFv14+KXU\r\n-----END RSA PRIVATE KEY-----" # noqa: E501
def env_var_2_bool(env_var: object) -> bool:
if isinstance(env_var, bool):
return env_var
if not isinstance(env_var, str):
return False
return env_var.lower().strip() == 'true'
@pytest.fixture(scope='session')
def bot_info():
return get_bot()
@ -370,66 +390,236 @@ def check_shortcut_signature(
expected_args.discard('self')
args_check = expected_args == effective_shortcut_args
if not args_check:
raise Exception(f'Expected arguments {expected_args}, got {effective_shortcut_args}')
# TODO: Also check annotation of return type. Would currently be a hassle b/c typing doesn't
# resolve `ForwardRef('Type')` to `Type`. For now we rely on MyPy, which probably allows the
# shortcuts to return more specific types than the bot method, but it's only annotations after
# all
annotation_check = True
for kwarg in effective_shortcut_args:
if bot_sig.parameters[kwarg].annotation != shortcut_sig.parameters[kwarg].annotation:
if isinstance(bot_sig.parameters[kwarg].annotation, type):
if bot_sig.parameters[kwarg].annotation.__name__ != str(
shortcut_sig.parameters[kwarg].annotation
):
print(
f'Expected {bot_sig.parameters[kwarg].annotation}, but '
f'got {shortcut_sig.parameters[kwarg].annotation}'
raise Exception(
f'For argument {kwarg} I expected {bot_sig.parameters[kwarg].annotation}, '
f'but got {shortcut_sig.parameters[kwarg].annotation}'
)
annotation_check = False
break
else:
print(
f'Expected {bot_sig.parameters[kwarg].annotation}, but '
raise Exception(
f'For argument {kwarg} I expected {bot_sig.parameters[kwarg].annotation}, but '
f'got {shortcut_sig.parameters[kwarg].annotation}'
)
annotation_check = False
break
bot_method_sig = inspect.signature(bot_method)
shortcut_sig = inspect.signature(shortcut)
default_check = all(
shortcut_sig.parameters[arg].default == bot_method_sig.parameters[arg].default
for arg in expected_args
)
for arg in expected_args:
if not shortcut_sig.parameters[arg].default == bot_method_sig.parameters[arg].default:
raise Exception(
f'Default for argument {arg} does not match the default of the Bot method.'
)
return args_check and annotation_check and default_check
return True
def check_shortcut_call(
kwargs: Dict[str, object],
bot_method: Callable,
shortcut_method: Callable,
bot: Bot,
bot_method_name: str,
skip_params: Iterable[str] = None,
shortcut_kwargs: Iterable[str] = None,
) -> bool:
"""
Checks that a shortcut passes all the existing arguments to the underlying bot method. Use as::
send_message = message.bot.send_message
def make_assertion(*_, **kwargs):
return check_shortcut_call(send_message, kwargs)
monkeypatch.setattr(message.bot, 'send_message', make_assertion)
assert message.reply_text('foobar')
assert check_shortcut_call(message.reply_text, message.bot, 'send_message')
Args:
kwargs: The kwargs passed to the bot method by the shortcut
bot_method: The bot method, e.g. :meth:`telegram.Bot.send_message`
shortcut_method: The shortcut method, e.g. `message.reply_text`
bot: The bot
bot_method_name: The bot methods name, e.g. `'send_message'`
skip_params: Parameters that are allowed to be missing, e.g. `['inline_message_id']`
shortcut_kwargs: The kwargs passed by the shortcut directly, e.g. ``chat_id``
Returns:
:obj:`bool`
"""
bot_signature = inspect.signature(bot_method)
expected_args = set(bot_signature.parameters.keys()).difference(['self'])
if not skip_params:
skip_params = set()
if not shortcut_kwargs:
shortcut_kwargs = set()
return expected_args == set(kwargs.keys())
orig_bot_method = getattr(bot, bot_method_name)
bot_signature = inspect.signature(orig_bot_method)
expected_args = set(bot_signature.parameters.keys()) - {'self'} - set(skip_params)
positional_args = {
name for name, param in bot_signature.parameters.items() if param.default == param.empty
}
ignored_args = positional_args | set(shortcut_kwargs)
shortcut_signature = inspect.signature(shortcut_method)
# auto_pagination: Special casing for InlineQuery.answer
kwargs = {name: name for name in shortcut_signature.parameters if name != 'auto_pagination'}
def make_assertion(**kw):
# name == value makes sure that
# a) we receive non-None input for all parameters
# b) we receive the correct input for each kwarg
received_kwargs = {
name for name, value in kw.items() if name in ignored_args or value == name
}
if not received_kwargs == expected_args:
raise Exception(
f'{orig_bot_method.__name__} did not receive correct value for the parameters '
f'{expected_args - received_kwargs}'
)
if bot_method_name == 'get_file':
# This is here mainly for PassportFile.get_file, which calls .set_credentials on the
# return value
return File(file_id='result', file_unique_id='result')
return True
setattr(bot, bot_method_name, make_assertion)
try:
shortcut_method(**kwargs)
except Exception as exc:
raise exc
finally:
setattr(bot, bot_method_name, orig_bot_method)
return True
def check_defaults_handling(
method: Callable,
bot: Bot,
return_value=None,
) -> bool:
"""
Checks that tg.ext.Defaults are handled correctly.
Args:
method: The shortcut/bot_method
bot: The bot
return_value: Optional. The return value of Bot._post that the method expects. Defaults to
None. get_file is automatically handled.
"""
def build_kwargs(signature: inspect.Signature, default_kwargs, dfv: Any = DEFAULT_NONE):
kws = {}
for name, param in signature.parameters.items():
# For required params we need to pass something
if param.default == param.empty:
# Some special casing
if name == 'permissions':
kws[name] = ChatPermissions()
elif name in ['prices', 'media', 'results', 'commands', 'errors']:
kws[name] = []
elif name == 'ok':
kws['ok'] = False
kws['error_message'] = 'error'
else:
kws[name] = True
# pass values for params that can have defaults only if we don't want to use the
# standard default
elif name in default_kwargs:
if dfv != DEFAULT_NONE:
kws[name] = dfv
# Some special casing for methods that have "exactly one of the optionals" type args
elif name in ['location', 'contact', 'venue', 'inline_message_id']:
kws[name] = True
return kws
shortcut_signature = inspect.signature(method)
kwargs_need_default = [
kwarg
for kwarg, value in shortcut_signature.parameters.items()
if isinstance(value.default, DefaultValue)
]
# shortcut_signature.parameters['timeout'] is of type DefaultValue
method_timeout = shortcut_signature.parameters['timeout'].default.value
default_kwarg_names = kwargs_need_default
# special case explanation_parse_mode of Bot.send_poll:
if 'explanation_parse_mode' in default_kwarg_names:
default_kwarg_names.remove('explanation_parse_mode')
defaults_no_custom_defaults = Defaults()
defaults_custom_defaults = Defaults(
**{kwarg: 'custom_default' for kwarg in default_kwarg_names}
)
expected_return_values = [None, []] if return_value is None else [return_value]
def make_assertion(_, data, timeout=DEFAULT_NONE, df_value=DEFAULT_NONE):
expected_timeout = method_timeout if df_value == DEFAULT_NONE else df_value
if timeout != expected_timeout:
pytest.fail(f'Got value {timeout} for "timeout", expected {expected_timeout}')
for arg in (dkw for dkw in kwargs_need_default if dkw != 'timeout'):
# 'None' should not be passed along to Telegram
if df_value in [None, DEFAULT_NONE]:
if arg in data:
pytest.fail(
f'Got value {data[arg]} for argument {arg}, expected it to be absent'
)
else:
value = data.get(arg, '`not passed at all`')
if value != df_value:
pytest.fail(f'Got value {value} for argument {arg} instead of {df_value}')
if method.__name__ in ['get_file', 'get_small_file', 'get_big_file']:
# This is here mainly for PassportFile.get_file, which calls .set_credentials on the
# return value
out = File(file_id='result', file_unique_id='result')
nonlocal expected_return_values
expected_return_values = [out]
return out.to_dict()
# Otherwise return None by default, as TGObject.de_json/list(None) in [None, []]
# That way we can check what gets passed to Request.post without having to actually
# make a request
# Some methods expect specific output, so we allow to customize that
return return_value
orig_post = bot.request.post
try:
for default_value, defaults in [
(DEFAULT_NONE, defaults_no_custom_defaults),
('custom_default', defaults_custom_defaults),
]:
bot.defaults = defaults
# 1: test that we get the correct default value, if we don't specify anything
kwargs = build_kwargs(
shortcut_signature,
kwargs_need_default,
)
assertion_callback = functools.partial(make_assertion, df_value=default_value)
setattr(bot.request, 'post', assertion_callback)
assert method(**kwargs) in expected_return_values
# 2: test that we get the manually passed non-None value
kwargs = build_kwargs(shortcut_signature, kwargs_need_default, dfv='non-None-value')
assertion_callback = functools.partial(make_assertion, df_value='non-None-value')
setattr(bot.request, 'post', assertion_callback)
assert method(**kwargs) in expected_return_values
# 3: test that we get the manually passed None value
kwargs = build_kwargs(
shortcut_signature,
kwargs_need_default,
dfv=None,
)
assertion_callback = functools.partial(make_assertion, df_value=None)
setattr(bot.request, 'post', assertion_callback)
assert method(**kwargs) in expected_return_values
except Exception as exc:
raise exc
finally:
setattr(bot.request, 'post', orig_post)
bot.defaults = None
return True

View file

@ -26,7 +26,7 @@ from flaky import flaky
from telegram import PhotoSize, Animation, Voice, TelegramError, MessageEntity, Bot
from telegram.error import BadRequest
from telegram.utils.helpers import escape_markdown
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='function')
@ -199,7 +199,6 @@ class TestAnimation:
def make_assertion(_, data, *args, **kwargs):
nonlocal test_flag
print(data.get('animation'), expected)
test_flag = data.get('animation') == expected and data.get('thumb') == expected
monkeypatch.setattr(bot, '_post', make_assertion)
@ -309,14 +308,14 @@ class TestAnimation:
bot.send_animation(chat_id=chat_id)
def test_get_file_instance_method(self, monkeypatch, animation):
get_file = animation.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == animation.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == animation.file_id
assert check_shortcut_signature(Animation.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(animation.get_file, animation.bot, 'get_file')
assert check_defaults_handling(animation.get_file, animation.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(animation.bot, 'get_file', make_assertion)
assert animation.get_file()
def test_equality(self):

View file

@ -24,7 +24,7 @@ from flaky import flaky
from telegram import Audio, TelegramError, Voice, MessageEntity, Bot
from telegram.utils.helpers import escape_markdown
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='function')
@ -282,14 +282,14 @@ class TestAudio:
bot.send_audio(chat_id=chat_id)
def test_get_file_instance_method(self, monkeypatch, audio):
get_file = audio.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == audio.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == audio.file_id
assert check_shortcut_signature(Audio.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(audio.get_file, audio.bot, 'get_file')
assert check_defaults_handling(audio.get_file, audio.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(audio.bot, 'get_file', make_assertion)
assert audio.get_file()
def test_equality(self, audio):

View file

@ -16,6 +16,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/].
import inspect
import time
import datetime as dtm
from pathlib import Path
@ -47,7 +48,7 @@ from telegram import (
from telegram.constants import MAX_INLINE_QUERY_RESULTS
from telegram.error import BadRequest, InvalidToken, NetworkError, RetryAfter
from telegram.utils.helpers import from_timestamp, escape_markdown, to_timestamp
from tests.conftest import expect_bad_request
from tests.conftest import expect_bad_request, check_defaults_handling
from tests.bots import FALLBACKS
@ -177,6 +178,40 @@ class TestBot:
if bot.last_name:
assert to_dict_bot["last_name"] == bot.last_name
@pytest.mark.parametrize(
'bot_method_name',
argvalues=[
name
for name, _ in inspect.getmembers(Bot, predicate=inspect.isfunction)
if not name.startswith('_')
and name
not in [
'de_json',
'de_list',
'to_dict',
'to_json',
'parse_data',
'get_updates',
'getUpdates',
]
],
)
def test_defaults_handling(self, bot_method_name, bot):
"""
Here we check that the bot methods handle tg.ext.Defaults correctly. As for most defaults,
we can't really check the effect, we just check if we're passing the correct kwargs to
Request.post. As bot method tests a scattered across the different test files, we do
this here in one place.
The same test is also run for all the shortcuts (Message.reply_text) etc in the
corresponding tests.
Finally, there are some tests for Defaults.{parse_mode, quote, allow_sending_without_reply}
at the appropriate places, as those are the only things we can actually check.
"""
bot_method = getattr(bot, bot_method_name)
assert check_defaults_handling(bot_method, bot)
@flaky(3, 1)
@pytest.mark.timeout(10)
def test_forward_message(self, bot, chat_id, message):
@ -354,7 +389,7 @@ class TestBot:
assert message_quiz.poll.explanation_entities == explanation_entities
@flaky(3, 1)
@pytest.mark.timeout(10)
@pytest.mark.timeout(15)
@pytest.mark.parametrize(['open_period', 'close_date'], [(5, None), (None, True)])
def test_send_open_period(self, bot, super_group_id, open_period, close_date):
question = 'Is this a test?'
@ -1790,8 +1825,8 @@ class TestBot:
'default_bot',
[
({'parse_mode': ParseMode.HTML, 'allow_sending_without_reply': True}),
({'parse_mode': False, 'allow_sending_without_reply': True}),
({'parse_mode': False, 'allow_sending_without_reply': False}),
({'parse_mode': None, 'allow_sending_without_reply': True}),
({'parse_mode': None, 'allow_sending_without_reply': False}),
],
indirect=['default_bot'],
)

View file

@ -143,7 +143,7 @@ class TestCallbackContext:
callback_context = CallbackContext.from_update(update, cdp)
with pytest.raises(AttributeError):
callback_context.chat_data = {"test": 123}
callback_context.bot_data = {"test": 123}
with pytest.raises(AttributeError):
callback_context.user_data = {}
with pytest.raises(AttributeError):

View file

@ -20,10 +20,10 @@
import pytest
from telegram import CallbackQuery, User, Message, Chat, Audio, Bot
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
@pytest.fixture(scope='class', params=['message', 'inline'])
@pytest.fixture(scope='function', params=['message', 'inline'])
def callback_query(bot, request):
cbq = CallbackQuery(
TestCallbackQuery.id_,
@ -50,6 +50,18 @@ class TestCallbackQuery:
inline_message_id = 'inline_message_id'
game_short_name = 'the_game'
@staticmethod
def skip_params(callback_query: CallbackQuery):
if callback_query.inline_message_id:
return {'message_id', 'chat_id'}
return {'inline_message_id'}
@staticmethod
def shortcut_kwargs(callback_query: CallbackQuery):
if not callback_query.inline_message_id:
return {'message_id', 'chat_id'}
return {'inline_message_id'}
@staticmethod
def check_passed_ids(callback_query: CallbackQuery, kwargs):
if callback_query.inline_message_id:
@ -97,28 +109,26 @@ class TestCallbackQuery:
assert callback_query_dict['game_short_name'] == callback_query.game_short_name
def test_answer(self, monkeypatch, callback_query):
answer_callback_query = callback_query.bot.answer_callback_query
def make_assertion(*_, **kwargs):
return kwargs['callback_query_id'] == callback_query.id and check_shortcut_call(
kwargs, answer_callback_query
)
return kwargs['callback_query_id'] == callback_query.id
assert check_shortcut_signature(
CallbackQuery.answer, Bot.answer_callback_query, ['callback_query_id'], []
)
assert check_shortcut_call(
callback_query.answer, callback_query.bot, 'answer_callback_query'
)
assert check_defaults_handling(callback_query.answer, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'answer_callback_query', make_assertion)
# TODO: PEP8
assert callback_query.answer()
def test_edit_message_text(self, monkeypatch, callback_query):
edit_message_text = callback_query.bot.edit_message_text
def make_assertion(*_, **kwargs):
text = kwargs['text'] == 'test'
ids = self.check_passed_ids(callback_query, kwargs)
return ids and text and check_shortcut_call(kwargs, edit_message_text)
return ids and text
assert check_shortcut_signature(
CallbackQuery.edit_message_text,
@ -126,18 +136,24 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.edit_message_text,
callback_query.bot,
'edit_message_text',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(callback_query.edit_message_text, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'edit_message_text', make_assertion)
assert callback_query.edit_message_text(text='test')
assert callback_query.edit_message_text('test')
def test_edit_message_caption(self, monkeypatch, callback_query):
edit_message_caption = callback_query.bot.edit_message_caption
def make_assertion(*_, **kwargs):
caption = kwargs['caption'] == 'new caption'
ids = self.check_passed_ids(callback_query, kwargs)
return ids and caption and check_shortcut_call(kwargs, edit_message_caption)
return ids and caption
assert check_shortcut_signature(
CallbackQuery.edit_message_caption,
@ -145,18 +161,24 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.edit_message_caption,
callback_query.bot,
'edit_message_caption',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(callback_query.edit_message_caption, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'edit_message_caption', make_assertion)
assert callback_query.edit_message_caption(caption='new caption')
assert callback_query.edit_message_caption('new caption')
def test_edit_message_reply_markup(self, monkeypatch, callback_query):
edit_message_reply_markup = callback_query.bot.edit_message_reply_markup
def make_assertion(*_, **kwargs):
reply_markup = kwargs['reply_markup'] == [['1', '2']]
ids = self.check_passed_ids(callback_query, kwargs)
return ids and reply_markup and check_shortcut_call(kwargs, edit_message_reply_markup)
return ids and reply_markup
assert check_shortcut_signature(
CallbackQuery.edit_message_reply_markup,
@ -164,18 +186,26 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.edit_message_reply_markup,
callback_query.bot,
'edit_message_reply_markup',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(
callback_query.edit_message_reply_markup, callback_query.bot
)
monkeypatch.setattr(callback_query.bot, 'edit_message_reply_markup', make_assertion)
assert callback_query.edit_message_reply_markup(reply_markup=[['1', '2']])
assert callback_query.edit_message_reply_markup([['1', '2']])
def test_edit_message_media(self, monkeypatch, callback_query):
edit_message_media = callback_query.bot.edit_message_media
def make_assertion(*_, **kwargs):
message_media = kwargs.get('media') == [['1', '2']]
ids = self.check_passed_ids(callback_query, kwargs)
return ids and message_media and check_shortcut_call(kwargs, edit_message_media)
return ids and message_media
assert check_shortcut_signature(
CallbackQuery.edit_message_media,
@ -183,24 +213,25 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.edit_message_media,
callback_query.bot,
'edit_message_media',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(callback_query.edit_message_media, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'edit_message_media', make_assertion)
assert callback_query.edit_message_media(media=[['1', '2']])
assert callback_query.edit_message_media([['1', '2']])
def test_edit_message_live_location(self, monkeypatch, callback_query):
edit_message_live_location = callback_query.bot.edit_message_live_location
def make_assertion(*_, **kwargs):
latitude = kwargs.get('latitude') == 1
longitude = kwargs.get('longitude') == 2
ids = self.check_passed_ids(callback_query, kwargs)
return (
ids
and latitude
and longitude
and check_shortcut_call(kwargs, edit_message_live_location)
)
return ids and latitude and longitude
assert check_shortcut_signature(
CallbackQuery.edit_message_live_location,
@ -208,17 +239,25 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.edit_message_live_location,
callback_query.bot,
'edit_message_live_location',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(
callback_query.edit_message_live_location, callback_query.bot
)
monkeypatch.setattr(callback_query.bot, 'edit_message_live_location', make_assertion)
assert callback_query.edit_message_live_location(latitude=1, longitude=2)
assert callback_query.edit_message_live_location(1, 2)
def test_stop_message_live_location(self, monkeypatch, callback_query):
stop_message_live_location = callback_query.bot.stop_message_live_location
def make_assertion(*_, **kwargs):
ids = self.check_passed_ids(callback_query, kwargs)
return ids and check_shortcut_call(kwargs, stop_message_live_location)
return ids
assert check_shortcut_signature(
CallbackQuery.stop_message_live_location,
@ -226,18 +265,26 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.stop_message_live_location,
callback_query.bot,
'stop_message_live_location',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(
callback_query.stop_message_live_location, callback_query.bot
)
monkeypatch.setattr(callback_query.bot, 'stop_message_live_location', make_assertion)
assert callback_query.stop_message_live_location()
def test_set_game_score(self, monkeypatch, callback_query):
set_game_score = callback_query.bot.set_game_score
def make_assertion(*_, **kwargs):
user_id = kwargs.get('user_id') == 1
score = kwargs.get('score') == 2
ids = self.check_passed_ids(callback_query, kwargs)
return ids and user_id and score and check_shortcut_call(kwargs, set_game_score)
return ids and user_id and score
assert check_shortcut_signature(
CallbackQuery.set_game_score,
@ -245,18 +292,24 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.set_game_score,
callback_query.bot,
'set_game_score',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(callback_query.set_game_score, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'set_game_score', make_assertion)
assert callback_query.set_game_score(user_id=1, score=2)
assert callback_query.set_game_score(1, 2)
def test_get_game_high_scores(self, monkeypatch, callback_query):
get_game_high_scores = callback_query.bot.get_game_high_scores
def make_assertion(*_, **kwargs):
user_id = kwargs.get('user_id') == 1
ids = self.check_passed_ids(callback_query, kwargs)
return ids and user_id and check_shortcut_call(kwargs, get_game_high_scores)
return ids and user_id
assert check_shortcut_signature(
CallbackQuery.get_game_high_scores,
@ -264,20 +317,27 @@ class TestCallbackQuery:
['inline_message_id', 'message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.get_game_high_scores,
callback_query.bot,
'get_game_high_scores',
skip_params=self.skip_params(callback_query),
shortcut_kwargs=self.shortcut_kwargs(callback_query),
)
assert check_defaults_handling(callback_query.get_game_high_scores, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'get_game_high_scores', make_assertion)
assert callback_query.get_game_high_scores(user_id=1)
assert callback_query.get_game_high_scores(1)
def test_delete_message(self, monkeypatch, callback_query):
delete_message = callback_query.bot.delete_message
if callback_query.inline_message_id:
pytest.skip("Can't delete inline messages")
def make_assertion(*args, **kwargs):
id_ = kwargs['chat_id'] == callback_query.message.chat_id
message = kwargs['message_id'] == callback_query.message.message_id
return id_ and message and check_shortcut_call(kwargs, delete_message)
return id_ and message
assert check_shortcut_signature(
CallbackQuery.delete_message,
@ -285,19 +345,20 @@ class TestCallbackQuery:
['message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.delete_message, callback_query.bot, 'delete_message'
)
assert check_defaults_handling(callback_query.delete_message, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'delete_message', make_assertion)
assert callback_query.delete_message()
def test_pin_message(self, monkeypatch, callback_query):
pin_message = callback_query.bot.pin_chat_message
if callback_query.inline_message_id:
pytest.skip("Can't pin inline messages")
def make_assertion(*args, **kwargs):
return kwargs['chat_id'] == callback_query.message.chat_id and check_shortcut_call(
kwargs, pin_message
)
return kwargs['chat_id'] == callback_query.message.chat_id
assert check_shortcut_signature(
CallbackQuery.pin_message,
@ -305,19 +366,20 @@ class TestCallbackQuery:
['message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.pin_message, callback_query.bot, 'pin_chat_message'
)
assert check_defaults_handling(callback_query.pin_message, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'pin_chat_message', make_assertion)
assert callback_query.pin_message()
def test_unpin_message(self, monkeypatch, callback_query):
unpin_message = callback_query.bot.unpin_chat_message
if callback_query.inline_message_id:
pytest.skip("Can't unpin inline messages")
def make_assertion(*args, **kwargs):
return kwargs['chat_id'] == callback_query.message.chat_id and check_shortcut_call(
kwargs, unpin_message
)
return kwargs['chat_id'] == callback_query.message.chat_id
assert check_shortcut_signature(
CallbackQuery.unpin_message,
@ -325,12 +387,18 @@ class TestCallbackQuery:
['message_id', 'chat_id'],
[],
)
assert check_shortcut_call(
callback_query.unpin_message,
callback_query.bot,
'unpin_chat_message',
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(callback_query.unpin_message, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'unpin_chat_message', make_assertion)
assert callback_query.unpin_message()
def test_copy_message(self, monkeypatch, callback_query):
copy_message = callback_query.bot.copy_message
if callback_query.inline_message_id:
pytest.skip("Can't copy inline messages")
@ -338,7 +406,7 @@ class TestCallbackQuery:
id_ = kwargs['from_chat_id'] == callback_query.message.chat_id
chat_id = kwargs['chat_id'] == 1
message = kwargs['message_id'] == callback_query.message.message_id
return id_ and message and chat_id and check_shortcut_call(kwargs, copy_message)
return id_ and message and chat_id
assert check_shortcut_signature(
CallbackQuery.copy_message,
@ -346,6 +414,8 @@ class TestCallbackQuery:
['message_id', 'from_chat_id'],
[],
)
assert check_shortcut_call(callback_query.copy_message, callback_query.bot, 'copy_message')
assert check_defaults_handling(callback_query.copy_message, callback_query.bot)
monkeypatch.setattr(callback_query.bot, 'copy_message', make_assertion)
assert callback_query.copy_message(1)

View file

@ -21,7 +21,7 @@ import pytest
from telegram import Chat, ChatAction, ChatPermissions, ChatLocation, Location, Bot
from telegram import User
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
@pytest.fixture(scope='class')
@ -126,153 +126,144 @@ class TestChat:
assert chat.full_name is None
def test_send_action(self, monkeypatch, chat):
send_chat_action = chat.bot.send_chat_action
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == chat.id
action = kwargs['action'] == ChatAction.TYPING
return id_ and action and check_shortcut_call(kwargs, send_chat_action)
return id_ and action
assert check_shortcut_signature(
Chat.send_chat_action, Bot.send_chat_action, ['chat_id'], []
)
assert check_shortcut_signature(chat.send_action, Bot.send_chat_action, ['chat_id'], [])
assert check_shortcut_call(chat.send_action, chat.bot, 'send_chat_action')
assert check_defaults_handling(chat.send_action, chat.bot)
monkeypatch.setattr(chat.bot, 'send_chat_action', make_assertion)
assert chat.send_action(action=ChatAction.TYPING)
assert chat.send_chat_action(action=ChatAction.TYPING)
assert chat.send_action(action=ChatAction.TYPING)
def test_leave(self, monkeypatch, chat):
leave_chat = chat.bot.leave_chat
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == chat.id and check_shortcut_call(kwargs, leave_chat)
return kwargs['chat_id'] == chat.id
assert check_shortcut_signature(Chat.leave, Bot.leave_chat, ['chat_id'], [])
assert check_shortcut_call(chat.leave, chat.bot, 'leave_chat')
assert check_defaults_handling(chat.leave, chat.bot)
monkeypatch.setattr(chat.bot, 'leave_chat', make_assertion)
assert chat.leave()
def test_get_administrators(self, monkeypatch, chat):
get_chat_administrators = chat.bot.get_chat_administrators
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == chat.id and check_shortcut_call(
kwargs, get_chat_administrators
)
return kwargs['chat_id'] == chat.id
assert check_shortcut_signature(
Chat.get_administrators, Bot.get_chat_administrators, ['chat_id'], []
)
assert check_shortcut_call(chat.get_administrators, chat.bot, 'get_chat_administrators')
assert check_defaults_handling(chat.get_administrators, chat.bot)
monkeypatch.setattr(chat.bot, 'get_chat_administrators', make_assertion)
assert chat.get_administrators()
def test_get_members_count(self, monkeypatch, chat):
get_chat_members_count = chat.bot.get_chat_members_count
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == chat.id and check_shortcut_call(
kwargs, get_chat_members_count
)
return kwargs['chat_id'] == chat.id
assert check_shortcut_signature(
Chat.get_members_count, Bot.get_chat_members_count, ['chat_id'], []
)
assert check_shortcut_call(chat.get_members_count, chat.bot, 'get_chat_members_count')
assert check_defaults_handling(chat.get_members_count, chat.bot)
monkeypatch.setattr(chat.bot, 'get_chat_members_count', make_assertion)
assert chat.get_members_count()
def test_get_member(self, monkeypatch, chat):
get_chat_member = chat.bot.get_chat_member
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == chat.id
user_id = kwargs['user_id'] == 42
return chat_id and user_id and check_shortcut_call(kwargs, get_chat_member)
return chat_id and user_id
assert check_shortcut_signature(Chat.get_member, Bot.get_chat_member, ['chat_id'], [])
assert check_shortcut_call(chat.get_member, chat.bot, 'get_chat_member')
assert check_defaults_handling(chat.get_member, chat.bot)
monkeypatch.setattr(chat.bot, 'get_chat_member', make_assertion)
assert chat.get_member(user_id=42)
def test_kick_member(self, monkeypatch, chat):
kick_chat_member = chat.bot.kick_chat_member
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == chat.id
user_id = kwargs['user_id'] == 42
until = kwargs['until_date'] == 43
return chat_id and user_id and until and check_shortcut_call(kwargs, kick_chat_member)
return chat_id and user_id and until
assert check_shortcut_signature(Chat.kick_member, Bot.kick_chat_member, ['chat_id'], [])
assert check_shortcut_call(chat.kick_member, chat.bot, 'kick_chat_member')
assert check_defaults_handling(chat.kick_member, chat.bot)
monkeypatch.setattr(chat.bot, 'kick_chat_member', make_assertion)
assert chat.kick_member(user_id=42, until_date=43)
@pytest.mark.parametrize('only_if_banned', [True, False, None])
def test_unban_member(self, monkeypatch, chat, only_if_banned):
unban_chat_member = chat.bot.unban_chat_member
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == chat.id
user_id = kwargs['user_id'] == 42
o_i_b = kwargs.get('only_if_banned', None) == only_if_banned
return chat_id and user_id and o_i_b and check_shortcut_call(kwargs, unban_chat_member)
return chat_id and user_id and o_i_b
assert check_shortcut_signature(Chat.unban_member, Bot.unban_chat_member, ['chat_id'], [])
assert check_shortcut_call(chat.unban_member, chat.bot, 'unban_chat_member')
assert check_defaults_handling(chat.unban_member, chat.bot)
monkeypatch.setattr(chat.bot, 'unban_chat_member', make_assertion)
assert chat.unban_member(user_id=42, only_if_banned=only_if_banned)
@pytest.mark.parametrize('is_anonymous', [True, False, None])
def test_promote_member(self, monkeypatch, chat, is_anonymous):
promote_chat_member = chat.bot.promote_chat_member
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == chat.id
user_id = kwargs['user_id'] == 42
o_i_b = kwargs.get('is_anonymous', None) == is_anonymous
return (
chat_id and user_id and o_i_b and check_shortcut_call(kwargs, promote_chat_member)
)
return chat_id and user_id and o_i_b
assert check_shortcut_signature(
Chat.promote_member, Bot.promote_chat_member, ['chat_id'], []
)
assert check_shortcut_call(chat.promote_member, chat.bot, 'promote_chat_member')
assert check_defaults_handling(chat.promote_member, chat.bot)
monkeypatch.setattr(chat.bot, 'promote_chat_member', make_assertion)
assert chat.promote_member(user_id=42, is_anonymous=is_anonymous)
def test_restrict_member(self, monkeypatch, chat):
restrict_chat_member = chat.bot.restrict_chat_member
permissions = ChatPermissions(True, False, True, False, True, False, True, False)
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == chat.id
user_id = kwargs['user_id'] == 42
o_i_b = kwargs.get('permissions', None) == permissions
return (
chat_id and user_id and o_i_b and check_shortcut_call(kwargs, restrict_chat_member)
)
return chat_id and user_id and o_i_b
assert check_shortcut_signature(
Chat.restrict_member, Bot.restrict_chat_member, ['chat_id'], []
)
assert check_shortcut_call(chat.restrict_member, chat.bot, 'restrict_chat_member')
assert check_defaults_handling(chat.restrict_member, chat.bot)
monkeypatch.setattr(chat.bot, 'restrict_chat_member', make_assertion)
assert chat.restrict_member(user_id=42, permissions=permissions)
def test_set_permissions(self, monkeypatch, chat):
set_chat_permissions = chat.bot.set_chat_permissions
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == chat.id
permissions = kwargs['permissions'] == self.permissions
return chat_id and permissions and check_shortcut_call(kwargs, set_chat_permissions)
return chat_id and permissions
assert check_shortcut_signature(
Chat.set_permissions, Bot.set_chat_permissions, ['chat_id'], []
)
assert check_shortcut_call(chat.set_permissions, chat.bot, 'set_chat_permissions')
assert check_defaults_handling(chat.set_permissions, chat.bot)
monkeypatch.setattr(chat.bot, 'set_chat_permissions', make_assertion)
assert chat.set_permissions(permissions=self.permissions)
@ -288,173 +279,133 @@ class TestChat:
assert chat.set_administrator_custom_title(user_id=42, custom_title='custom_title')
def test_pin_message(self, monkeypatch, chat):
pin_chat_message = chat.bot.pin_chat_message
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['message_id'] == 42
and check_shortcut_call(kwargs, pin_chat_message)
)
return kwargs['chat_id'] == chat.id and kwargs['message_id'] == 42
assert check_shortcut_signature(Chat.pin_message, Bot.pin_chat_message, ['chat_id'], [])
assert check_shortcut_call(chat.pin_message, chat.bot, 'pin_chat_message')
assert check_defaults_handling(chat.pin_message, chat.bot)
monkeypatch.setattr(chat.bot, 'pin_chat_message', make_assertion)
assert chat.pin_message(message_id=42)
def test_unpin_message(self, monkeypatch, chat):
unpin_chat_message = chat.bot.unpin_chat_message
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == chat.id and check_shortcut_call(kwargs, unpin_chat_message)
return kwargs['chat_id'] == chat.id
assert check_shortcut_signature(
Chat.unpin_message, Bot.unpin_chat_message, ['chat_id'], []
)
assert check_shortcut_call(chat.unpin_message, chat.bot, 'unpin_chat_message')
assert check_defaults_handling(chat.unpin_message, chat.bot)
monkeypatch.setattr(chat.bot, 'unpin_chat_message', make_assertion)
assert chat.unpin_message()
def test_unpin_all_messages(self, monkeypatch, chat):
unpin_all_chat_messages = chat.bot.unpin_all_chat_messages
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == chat.id and check_shortcut_call(
kwargs, unpin_all_chat_messages
)
return kwargs['chat_id'] == chat.id
assert check_shortcut_signature(
Chat.unpin_all_messages, Bot.unpin_all_chat_messages, ['chat_id'], []
)
assert check_shortcut_call(chat.unpin_all_messages, chat.bot, 'unpin_all_chat_messages')
assert check_defaults_handling(chat.unpin_all_messages, chat.bot)
monkeypatch.setattr(chat.bot, 'unpin_all_chat_messages', make_assertion)
assert chat.unpin_all_messages()
def test_instance_method_send_message(self, monkeypatch, chat):
send_message = chat.bot.send_message
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['text'] == 'test'
and check_shortcut_call(kwargs, send_message)
)
return kwargs['chat_id'] == chat.id and kwargs['text'] == 'test'
assert check_shortcut_signature(Chat.send_message, Bot.send_message, ['chat_id'], [])
assert check_shortcut_call(chat.send_message, chat.bot, 'send_message')
assert check_defaults_handling(chat.send_message, chat.bot)
monkeypatch.setattr(chat.bot, 'send_message', make_assertion)
assert chat.send_message(text='test')
def test_instance_method_send_media_group(self, monkeypatch, chat):
send_media_group = chat.bot.send_media_group
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['media'] == 'test_media_group'
and check_shortcut_call(kwargs, send_media_group)
)
return kwargs['chat_id'] == chat.id and kwargs['media'] == 'test_media_group'
assert check_shortcut_signature(
Chat.send_media_group, Bot.send_media_group, ['chat_id'], []
)
assert check_shortcut_call(chat.send_media_group, chat.bot, 'send_media_group')
assert check_defaults_handling(chat.send_media_group, chat.bot)
monkeypatch.setattr(chat.bot, 'send_media_group', make_assertion)
assert chat.send_media_group(media='test_media_group')
def test_instance_method_send_photo(self, monkeypatch, chat):
send_photo = chat.bot.send_photo
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['photo'] == 'test_photo'
and check_shortcut_call(kwargs, send_photo)
)
return kwargs['chat_id'] == chat.id and kwargs['photo'] == 'test_photo'
assert check_shortcut_signature(Chat.send_photo, Bot.send_photo, ['chat_id'], [])
assert check_shortcut_call(chat.send_photo, chat.bot, 'send_photo')
assert check_defaults_handling(chat.send_photo, chat.bot)
monkeypatch.setattr(chat.bot, 'send_photo', make_assertion)
assert chat.send_photo(photo='test_photo')
def test_instance_method_send_contact(self, monkeypatch, chat):
send_contact = chat.bot.send_contact
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['phone_number'] == 'test_contact'
and check_shortcut_call(kwargs, send_contact)
)
return kwargs['chat_id'] == chat.id and kwargs['phone_number'] == 'test_contact'
assert check_shortcut_signature(Chat.send_contact, Bot.send_contact, ['chat_id'], [])
assert check_shortcut_call(chat.send_contact, chat.bot, 'send_contact')
assert check_defaults_handling(chat.send_contact, chat.bot)
monkeypatch.setattr(chat.bot, 'send_contact', make_assertion)
assert chat.send_contact(phone_number='test_contact')
def test_instance_method_send_audio(self, monkeypatch, chat):
send_audio = chat.bot.send_audio
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['audio'] == 'test_audio'
and check_shortcut_call(kwargs, send_audio)
)
return kwargs['chat_id'] == chat.id and kwargs['audio'] == 'test_audio'
assert check_shortcut_signature(Chat.send_audio, Bot.send_audio, ['chat_id'], [])
assert check_shortcut_call(chat.send_audio, chat.bot, 'send_audio')
assert check_defaults_handling(chat.send_audio, chat.bot)
monkeypatch.setattr(chat.bot, 'send_audio', make_assertion)
assert chat.send_audio(audio='test_audio')
def test_instance_method_send_document(self, monkeypatch, chat):
send_document = chat.bot.send_document
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['document'] == 'test_document'
and check_shortcut_call(kwargs, send_document)
)
return kwargs['chat_id'] == chat.id and kwargs['document'] == 'test_document'
assert check_shortcut_signature(Chat.send_document, Bot.send_document, ['chat_id'], [])
assert check_shortcut_call(chat.send_document, chat.bot, 'send_document')
assert check_defaults_handling(chat.send_document, chat.bot)
monkeypatch.setattr(chat.bot, 'send_document', make_assertion)
assert chat.send_document(document='test_document')
def test_instance_method_send_dice(self, monkeypatch, chat):
send_dice = chat.bot.send_dice
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['emoji'] == 'test_dice'
and check_shortcut_call(kwargs, send_dice)
)
return kwargs['chat_id'] == chat.id and kwargs['emoji'] == 'test_dice'
assert check_shortcut_signature(Chat.send_dice, Bot.send_dice, ['chat_id'], [])
assert check_shortcut_call(chat.send_dice, chat.bot, 'send_dice')
assert check_defaults_handling(chat.send_dice, chat.bot)
monkeypatch.setattr(chat.bot, 'send_dice', make_assertion)
assert chat.send_dice(emoji='test_dice')
def test_instance_method_send_game(self, monkeypatch, chat):
send_game = chat.bot.send_game
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['game_short_name'] == 'test_game'
and check_shortcut_call(kwargs, send_game)
)
return kwargs['chat_id'] == chat.id and kwargs['game_short_name'] == 'test_game'
assert check_shortcut_signature(Chat.send_game, Bot.send_game, ['chat_id'], [])
assert check_shortcut_call(chat.send_game, chat.bot, 'send_game')
assert check_defaults_handling(chat.send_game, chat.bot)
monkeypatch.setattr(chat.bot, 'send_game', make_assertion)
assert chat.send_game(game_short_name='test_game')
def test_instance_method_send_invoice(self, monkeypatch, chat):
send_invoice = chat.bot.send_invoice
def make_assertion(*_, **kwargs):
title = kwargs['title'] == 'title'
description = kwargs['description'] == 'description'
@ -472,11 +423,11 @@ class TestChat:
and currency
and prices
)
return (
kwargs['chat_id'] == chat.id and args and check_shortcut_call(kwargs, send_invoice)
)
return kwargs['chat_id'] == chat.id and args
assert check_shortcut_signature(Chat.send_invoice, Bot.send_invoice, ['chat_id'], [])
assert check_shortcut_call(chat.send_invoice, chat.bot, 'send_invoice')
assert check_defaults_handling(chat.send_invoice, chat.bot)
monkeypatch.setattr(chat.bot, 'send_invoice', make_assertion)
assert chat.send_invoice(
@ -490,159 +441,117 @@ class TestChat:
)
def test_instance_method_send_location(self, monkeypatch, chat):
send_location = chat.bot.send_location
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['latitude'] == 'test_location'
and check_shortcut_call(kwargs, send_location)
)
return kwargs['chat_id'] == chat.id and kwargs['latitude'] == 'test_location'
assert check_shortcut_signature(Chat.send_location, Bot.send_location, ['chat_id'], [])
assert check_shortcut_call(chat.send_location, chat.bot, 'send_location')
assert check_defaults_handling(chat.send_location, chat.bot)
monkeypatch.setattr(chat.bot, 'send_location', make_assertion)
assert chat.send_location(latitude='test_location')
def test_instance_method_send_sticker(self, monkeypatch, chat):
send_sticker = chat.bot.send_sticker
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['sticker'] == 'test_sticker'
and check_shortcut_call(kwargs, send_sticker)
)
return kwargs['chat_id'] == chat.id and kwargs['sticker'] == 'test_sticker'
assert check_shortcut_signature(Chat.send_sticker, Bot.send_sticker, ['chat_id'], [])
assert check_shortcut_call(chat.send_sticker, chat.bot, 'send_sticker')
assert check_defaults_handling(chat.send_sticker, chat.bot)
monkeypatch.setattr(chat.bot, 'send_sticker', make_assertion)
assert chat.send_sticker(sticker='test_sticker')
def test_instance_method_send_venue(self, monkeypatch, chat):
send_venue = chat.bot.send_venue
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['title'] == 'test_venue'
and check_shortcut_call(kwargs, send_venue)
)
return kwargs['chat_id'] == chat.id and kwargs['title'] == 'test_venue'
assert check_shortcut_signature(Chat.send_venue, Bot.send_venue, ['chat_id'], [])
assert check_shortcut_call(chat.send_venue, chat.bot, 'send_venue')
assert check_defaults_handling(chat.send_venue, chat.bot)
monkeypatch.setattr(chat.bot, 'send_venue', make_assertion)
assert chat.send_venue(title='test_venue')
def test_instance_method_send_video(self, monkeypatch, chat):
send_video = chat.bot.send_video
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['video'] == 'test_video'
and check_shortcut_call(kwargs, send_video)
)
return kwargs['chat_id'] == chat.id and kwargs['video'] == 'test_video'
assert check_shortcut_signature(Chat.send_video, Bot.send_video, ['chat_id'], [])
assert check_shortcut_call(chat.send_video, chat.bot, 'send_video')
assert check_defaults_handling(chat.send_video, chat.bot)
monkeypatch.setattr(chat.bot, 'send_video', make_assertion)
assert chat.send_video(video='test_video')
def test_instance_method_send_video_note(self, monkeypatch, chat):
send_video_note = chat.bot.send_video_note
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['video_note'] == 'test_video_note'
and check_shortcut_call(kwargs, send_video_note)
)
return kwargs['chat_id'] == chat.id and kwargs['video_note'] == 'test_video_note'
assert check_shortcut_signature(Chat.send_video_note, Bot.send_video_note, ['chat_id'], [])
assert check_shortcut_call(chat.send_video_note, chat.bot, 'send_video_note')
assert check_defaults_handling(chat.send_video_note, chat.bot)
monkeypatch.setattr(chat.bot, 'send_video_note', make_assertion)
assert chat.send_video_note(video_note='test_video_note')
def test_instance_method_send_voice(self, monkeypatch, chat):
send_voice = chat.bot.send_voice
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['voice'] == 'test_voice'
and check_shortcut_call(kwargs, send_voice)
)
return kwargs['chat_id'] == chat.id and kwargs['voice'] == 'test_voice'
assert check_shortcut_signature(Chat.send_voice, Bot.send_voice, ['chat_id'], [])
assert check_shortcut_call(chat.send_voice, chat.bot, 'send_voice')
assert check_defaults_handling(chat.send_voice, chat.bot)
monkeypatch.setattr(chat.bot, 'send_voice', make_assertion)
assert chat.send_voice(voice='test_voice')
def test_instance_method_send_animation(self, monkeypatch, chat):
send_animation = chat.bot.send_animation
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['animation'] == 'test_animation'
and check_shortcut_call(kwargs, send_animation)
)
return kwargs['chat_id'] == chat.id and kwargs['animation'] == 'test_animation'
assert check_shortcut_signature(Chat.send_animation, Bot.send_animation, ['chat_id'], [])
assert check_shortcut_call(chat.send_animation, chat.bot, 'send_animation')
assert check_defaults_handling(chat.send_animation, chat.bot)
monkeypatch.setattr(chat.bot, 'send_animation', make_assertion)
assert chat.send_animation(animation='test_animation')
def test_instance_method_send_poll(self, monkeypatch, chat):
send_poll = chat.bot.send_poll
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == chat.id
and kwargs['question'] == 'test_poll'
and check_shortcut_call(kwargs, send_poll)
)
return kwargs['chat_id'] == chat.id and kwargs['question'] == 'test_poll'
assert check_shortcut_signature(Chat.send_poll, Bot.send_poll, ['chat_id'], [])
assert check_shortcut_call(chat.send_poll, chat.bot, 'send_poll')
assert check_defaults_handling(chat.send_poll, chat.bot)
monkeypatch.setattr(chat.bot, 'send_poll', make_assertion)
assert chat.send_poll(question='test_poll', options=[1, 2])
def test_instance_method_send_copy(self, monkeypatch, chat):
copy_message = chat.bot.copy_message
def make_assertion(*_, **kwargs):
from_chat_id = kwargs['from_chat_id'] == 'test_copy'
message_id = kwargs['message_id'] == 42
chat_id = kwargs['chat_id'] == chat.id
return (
from_chat_id
and message_id
and chat_id
and check_shortcut_call(kwargs, copy_message)
)
return from_chat_id and message_id and chat_id
assert check_shortcut_signature(Chat.send_copy, Bot.copy_message, ['chat_id'], [])
assert check_shortcut_call(chat.copy_message, chat.bot, 'copy_message')
assert check_defaults_handling(chat.copy_message, chat.bot)
monkeypatch.setattr(chat.bot, 'copy_message', make_assertion)
assert chat.send_copy(from_chat_id='test_copy', message_id=42)
def test_instance_method_copy_message(self, monkeypatch, chat):
copy_message = chat.bot.copy_message
def make_assertion(*_, **kwargs):
from_chat_id = kwargs['from_chat_id'] == chat.id
message_id = kwargs['message_id'] == 42
chat_id = kwargs['chat_id'] == 'test_copy'
return (
from_chat_id
and message_id
and chat_id
and check_shortcut_call(kwargs, copy_message)
)
return from_chat_id and message_id and chat_id
assert check_shortcut_signature(Chat.copy_message, Bot.copy_message, ['from_chat_id'], [])
assert check_shortcut_call(chat.copy_message, chat.bot, 'copy_message')
assert check_defaults_handling(chat.copy_message, chat.bot)
monkeypatch.setattr(chat.bot, 'copy_message', make_assertion)
assert chat.copy_message(chat_id='test_copy', message_id=42)

View file

@ -22,7 +22,12 @@ import pytest
from flaky import flaky
from telegram import ChatPhoto, Voice, TelegramError, Bot
from tests.conftest import expect_bad_request, check_shortcut_call, check_shortcut_signature
from tests.conftest import (
expect_bad_request,
check_shortcut_call,
check_shortcut_signature,
check_defaults_handling,
)
@pytest.fixture(scope='function')
@ -125,29 +130,25 @@ class TestChatPhoto:
bot.set_chat_photo(chat_id=super_group_id)
def test_get_small_file_instance_method(self, monkeypatch, chat_photo):
get_small_file = chat_photo.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == chat_photo.small_file_id and check_shortcut_call(
kwargs, get_small_file
)
return kwargs['file_id'] == chat_photo.small_file_id
assert check_shortcut_signature(ChatPhoto.get_small_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(chat_photo.get_small_file, chat_photo.bot, 'get_file')
assert check_defaults_handling(chat_photo.get_small_file, chat_photo.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(chat_photo.bot, 'get_file', make_assertion)
assert chat_photo.get_small_file()
def test_get_big_file_instance_method(self, monkeypatch, chat_photo):
get_big_file = chat_photo.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == chat_photo.big_file_id and check_shortcut_call(
kwargs, get_big_file
)
return kwargs['file_id'] == chat_photo.big_file_id
assert check_shortcut_signature(ChatPhoto.get_big_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(chat_photo.get_big_file, chat_photo.bot, 'get_file')
assert check_defaults_handling(chat_photo.get_big_file, chat_photo.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(chat_photo.bot, 'get_file', make_assertion)
assert chat_photo.get_big_file()
def test_equality(self):

View file

@ -32,7 +32,6 @@ class TestConstants:
with pytest.raises(
BadRequest,
match='Message is too long',
message='MAX_MESSAGE_LENGTH is no longer valid',
):
bot.send_message(chat_id=chat_id, text='a' * (constants.MAX_MESSAGE_LENGTH + 1))
@ -48,7 +47,6 @@ class TestConstants:
with pytest.raises(
BadRequest,
match="Media_caption_too_long",
message='MAX_CAPTION_LENGTH is no longer valid',
):
with open('tests/data/telegram.png', 'rb') as f:
bot.send_photo(photo=f, caption=bad_caption, chat_id=chat_id)

View file

@ -29,6 +29,8 @@ class TestDefault:
with pytest.raises(AttributeError):
defaults.parse_mode = True
with pytest.raises(AttributeError):
defaults.explanation_parse_mode = True
with pytest.raises(AttributeError):
defaults.disable_notification = True
with pytest.raises(AttributeError):

View file

@ -25,7 +25,7 @@ from flaky import flaky
from telegram import Document, PhotoSize, TelegramError, Voice, MessageEntity, Bot
from telegram.error import BadRequest
from telegram.utils.helpers import escape_markdown
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
@pytest.fixture(scope='function')
@ -298,14 +298,14 @@ class TestDocument:
bot.send_document(chat_id=chat_id)
def test_get_file_instance_method(self, monkeypatch, document):
get_file = document.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == document.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == document.file_id
assert check_shortcut_signature(Document.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(document.get_file, document.bot, 'get_file')
assert check_defaults_handling(document.get_file, document.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(document.bot, 'get_file', make_assertion)
assert document.get_file()
def test_equality(self, document):

View file

@ -115,7 +115,6 @@ class TestErrors:
],
)
def test_errors_pickling(self, exception, attributes):
print(exception)
pickled = pickle.dumps(exception)
unpickled = pickle.loads(pickled)
assert type(unpickled) is type(exception)

View file

@ -547,7 +547,7 @@ class TestFilters:
assert not Filters.document.audio(update)
update.message.document.mime_type = (
"application/vnd.openxmlformats-officedocument." "wordprocessingml.document"
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
)
assert Filters.document.docx(update)
assert Filters.document.application(update)

View file

@ -17,12 +17,11 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import os
import subprocess
import sys
import time
import datetime as dtm
from importlib import reload
from pathlib import Path
from unittest import mock
import pytest
@ -37,6 +36,8 @@ from telegram.utils.helpers import _datetime_to_float_timestamp
# sample time specification values categorised into absolute / delta / time-of-day
from tests.conftest import env_var_2_bool
ABSOLUTE_TIME_SPECS = [
dtm.datetime.now(tz=dtm.timezone(dtm.timedelta(hours=-7))),
dtm.datetime.utcnow(),
@ -49,28 +50,41 @@ TIME_OF_DAY_TIME_SPECS = [
RELATIVE_TIME_SPECS = DELTA_TIME_SPECS + TIME_OF_DAY_TIME_SPECS
TIME_SPECS = ABSOLUTE_TIME_SPECS + RELATIVE_TIME_SPECS
"""
This part is here for ptb-raw, where we don't have pytz (unless the user installs it)
Because imports in pytest are intricate, we just run
# This is here for ptb-raw, where we don't have pytz (unless the user installs it)
@pytest.fixture(scope='function', params=[True, False])
def pytz_install(request):
skip = not os.getenv('GITHUB_ACTIONS', False)
reason = 'Un/installing pytz slows tests down, so we just do that in CI'
pytest -k test_helpers.py
if not request.param:
if skip:
pytest.skip(reason)
subprocess.check_call([sys.executable, "-m", "pip", "uninstall", "pytz", "-y"])
del sys.modules['pytz']
reload(helpers)
yield
if not request.param:
if skip:
pytest.skip(reason)
subprocess.check_call([sys.executable, "-m", "pip", "install", "pytz"])
with the TEST_NO_PYTZ environment variable set in addition to the regular test suite.
Because actually uninstalling pytz would lead to errors in the test suite we just mock the
import to raise the expected exception.
Note that a fixture that just does this for every test that needs it is a nice idea, but for some
reason makes test_updater.py hang indefinitely on GitHub Actions (at least when Hinrich tried that)
"""
TEST_NO_PYTZ = env_var_2_bool(os.getenv('TEST_NO_PYTZ', False))
if TEST_NO_PYTZ:
orig_import = __import__
def import_mock(module_name, *args, **kwargs):
if module_name == 'pytz':
raise ModuleNotFoundError('We are testing without pytz here')
return orig_import(module_name, *args, **kwargs)
with mock.patch('builtins.__import__', side_effect=import_mock):
reload(helpers)
class TestHelpers:
def test_helpers_utc(self):
# Here we just test, that we got the correct UTC variant
if TEST_NO_PYTZ:
assert helpers.UTC is helpers.DTM_UTC
else:
assert helpers.UTC is not helpers.DTM_UTC
def test_escape_markdown(self):
test_str = '*bold*, _italic_, `code`, [text_link](http://github.com/)'
expected_str = r'\*bold\*, \_italic\_, \`code\`, \[text\_link](http://github.com/)'
@ -108,14 +122,14 @@ class TestHelpers:
with pytest.raises(ValueError):
helpers.escape_markdown('abc', version=-1)
def test_to_float_timestamp_absolute_naive(self, pytz_install):
def test_to_float_timestamp_absolute_naive(self):
"""Conversion from timezone-naive datetime to timestamp.
Naive datetimes should be assumed to be in UTC.
"""
datetime = dtm.datetime(2019, 11, 11, 0, 26, 16, 10 ** 5)
assert helpers.to_float_timestamp(datetime) == 1573431976.1
def test_to_float_timestamp_absolute_naive_no_pytz(self, monkeypatch, pytz_install):
def test_to_float_timestamp_absolute_naive_no_pytz(self, monkeypatch):
"""Conversion from timezone-naive datetime to timestamp.
Naive datetimes should be assumed to be in UTC.
"""
@ -146,7 +160,7 @@ class TestHelpers:
delta = time_spec.total_seconds() if hasattr(time_spec, 'total_seconds') else time_spec
assert helpers.to_float_timestamp(time_spec, reference_t) == reference_t + delta
def test_to_float_timestamp_time_of_day(self, pytz_install):
def test_to_float_timestamp_time_of_day(self):
"""Conversion from time-of-day specification to timestamp"""
hour, hour_delta = 12, 1
ref_t = _datetime_to_float_timestamp(dtm.datetime(1970, 1, 1, hour=hour))
@ -173,7 +187,7 @@ class TestHelpers:
)
@pytest.mark.parametrize('time_spec', RELATIVE_TIME_SPECS, ids=str)
def test_to_float_timestamp_default_reference(self, time_spec, pytz_install):
def test_to_float_timestamp_default_reference(self, time_spec):
"""The reference timestamp for relative time specifications should default to now"""
now = time.time()
assert helpers.to_float_timestamp(time_spec) == pytest.approx(
@ -185,7 +199,7 @@ class TestHelpers:
helpers.to_float_timestamp(Defaults())
@pytest.mark.parametrize('time_spec', TIME_SPECS, ids=str)
def test_to_timestamp(self, time_spec, pytz_install):
def test_to_timestamp(self, time_spec):
# delegate tests to `to_float_timestamp`
assert helpers.to_timestamp(time_spec) == int(helpers.to_float_timestamp(time_spec))
@ -196,7 +210,7 @@ class TestHelpers:
def test_from_timestamp_none(self):
assert helpers.from_timestamp(None) is None
def test_from_timestamp_naive(self, pytz_install):
def test_from_timestamp_naive(self):
datetime = dtm.datetime(2019, 11, 11, 0, 26, 16, tzinfo=None)
assert helpers.from_timestamp(1573431976, tzinfo=None) == datetime

View file

@ -20,7 +20,7 @@
import pytest
from telegram import User, Location, InlineQuery, Update, Bot
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
@pytest.fixture(scope='class')
@ -69,16 +69,14 @@ class TestInlineQuery:
assert inline_query_dict['offset'] == inline_query.offset
def test_answer(self, monkeypatch, inline_query):
answer_inline_query = inline_query.bot.answer_inline_query
def make_assertion(*_, **kwargs):
return kwargs['inline_query_id'] == inline_query.id and check_shortcut_call(
kwargs, answer_inline_query
)
return kwargs['inline_query_id'] == inline_query.id
assert check_shortcut_signature(
InlineQuery.answer, Bot.answer_inline_query, ['inline_query_id'], ['auto_pagination']
)
assert check_shortcut_call(inline_query.answer, inline_query.bot, 'answer_inline_query')
assert check_defaults_handling(inline_query.answer, inline_query.bot)
monkeypatch.setattr(inline_query.bot, 'answer_inline_query', make_assertion)
assert inline_query.answer(results=[])

View file

@ -30,6 +30,7 @@ from telegram import (
InputMediaAudio,
InputMediaDocument,
MessageEntity,
ParseMode,
)
# noinspection PyUnresolvedReferences
@ -551,3 +552,80 @@ class TestSendMediaGroup:
chat_id=cid, message_id=mid, media=InputMediaPhoto(thumb_file)
)
assert isinstance(new_message, Message)
@flaky(3, 1)
@pytest.mark.timeout(10)
@pytest.mark.parametrize(
'default_bot', [{'parse_mode': ParseMode.HTML}], indirect=True, ids=['HTML-Bot']
)
@pytest.mark.parametrize('media_type', ['animation', 'document', 'audio', 'photo', 'video'])
def test_edit_message_media_default_parse_mode(
self,
chat_id,
default_bot,
media_type,
animation, # noqa: F811
document, # noqa: F811
audio, # noqa: F811
photo, # noqa: F811
video, # noqa: F811
):
html_caption = '<b>bold</b> <i>italic</i> <code>code</code>'
markdown_caption = '*bold* _italic_ `code`'
test_caption = 'bold italic code'
test_entities = [
MessageEntity(MessageEntity.BOLD, 0, 4),
MessageEntity(MessageEntity.ITALIC, 5, 6),
MessageEntity(MessageEntity.CODE, 12, 4),
]
def build_media(parse_mode, med_type):
kwargs = {}
if parse_mode != ParseMode.HTML:
kwargs['parse_mode'] = parse_mode
kwargs['caption'] = markdown_caption
else:
kwargs['caption'] = html_caption
if med_type == 'animation':
return InputMediaAnimation(animation, **kwargs)
if med_type == 'document':
return InputMediaDocument(document, **kwargs)
if med_type == 'audio':
return InputMediaAudio(audio, **kwargs)
if med_type == 'photo':
return InputMediaPhoto(photo, **kwargs)
if med_type == 'video':
return InputMediaVideo(video, **kwargs)
message = default_bot.send_photo(chat_id, photo)
message = default_bot.edit_message_media(
message.chat_id,
message.message_id,
media=build_media(parse_mode=ParseMode.HTML, med_type=media_type),
)
assert message.caption == test_caption
assert message.caption_entities == test_entities
# Remove caption to avoid "Message not changed"
message.edit_caption()
message = default_bot.edit_message_media(
message.chat_id,
message.message_id,
media=build_media(parse_mode=ParseMode.MARKDOWN_V2, med_type=media_type),
)
assert message.caption == test_caption
assert message.caption_entities == test_entities
# Remove caption to avoid "Message not changed"
message.edit_caption()
message = default_bot.edit_message_media(
message.chat_id,
message.message_id,
media=build_media(parse_mode=None, med_type=media_type),
)
assert message.caption == markdown_caption
assert message.caption_entities == []

View file

@ -50,7 +50,7 @@ from telegram import (
ChatAction,
)
from telegram.ext import Defaults
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
from tests.test_passport import RAW_PASSPORT_DATA
@ -638,8 +638,6 @@ class TestMessage:
assert message_params.effective_attachment == item
def test_reply_text(self, monkeypatch, message):
send_message = message.bot.send_message
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
text = kwargs['text'] == 'test'
@ -647,11 +645,13 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and text and reply and check_shortcut_call(kwargs, send_message)
return id_ and text and reply
assert check_shortcut_signature(
Message.reply_text, Bot.send_message, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_text, message.bot, 'send_message')
assert check_defaults_handling(message.reply_text, message.bot)
monkeypatch.setattr(message.bot, 'send_message', make_assertion)
assert message.reply_text('test')
@ -659,7 +659,6 @@ class TestMessage:
assert message.reply_text('test', reply_to_message_id=message.message_id, quote=True)
def test_reply_markdown(self, monkeypatch, message):
send_message = message.bot.send_message
test_md_string = (
r'Test for <*bold*, _ita_\__lic_, `code`, '
'[links](http://github.com/ab_), '
@ -675,13 +674,13 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return all([cid, markdown_text, reply, markdown_enabled]) and check_shortcut_call(
kwargs, send_message
)
return all([cid, markdown_text, reply, markdown_enabled])
assert check_shortcut_signature(
Message.reply_markdown, Bot.send_message, ['chat_id', 'parse_mode'], ['quote']
)
assert check_shortcut_call(message.reply_text, message.bot, 'send_message')
assert check_defaults_handling(message.reply_text, message.bot)
text_markdown = self.test_message.text_markdown
assert text_markdown == test_md_string
@ -694,7 +693,6 @@ class TestMessage:
)
def test_reply_markdown_v2(self, monkeypatch, message):
send_message = message.bot.send_message
test_md_string = (
r'__Test__ for <*bold*, _ita\_lic_, `\\\`code`, '
'[links](http://github.com/abc\\\\\\)def), '
@ -711,13 +709,13 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return all([cid, markdown_text, reply, markdown_enabled]) and check_shortcut_call(
kwargs, send_message
)
return all([cid, markdown_text, reply, markdown_enabled])
assert check_shortcut_signature(
Message.reply_markdown_v2, Bot.send_message, ['chat_id', 'parse_mode'], ['quote']
)
assert check_shortcut_call(message.reply_text, message.bot, 'send_message')
assert check_defaults_handling(message.reply_text, message.bot)
text_markdown = self.test_message_v2.text_markdown_v2
assert text_markdown == test_md_string
@ -732,7 +730,6 @@ class TestMessage:
)
def test_reply_html(self, monkeypatch, message):
send_message = message.bot.send_message
test_html_string = (
'<u>Test</u> for &lt;<b>bold</b>, <i>ita_lic</i>, '
r'<code>\`code</code>, '
@ -751,13 +748,13 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return all([cid, html_text, reply, html_enabled]) and check_shortcut_call(
kwargs, send_message
)
return all([cid, html_text, reply, html_enabled])
assert check_shortcut_signature(
Message.reply_html, Bot.send_message, ['chat_id', 'parse_mode'], ['quote']
)
assert check_shortcut_call(message.reply_text, message.bot, 'send_message')
assert check_defaults_handling(message.reply_text, message.bot)
text_html = self.test_message_v2.text_html
assert text_html == test_html_string
@ -770,8 +767,6 @@ class TestMessage:
)
def test_reply_media_group(self, monkeypatch, message):
send_media_group = message.bot.send_media_group
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
media = kwargs['media'] == 'reply_media_group'
@ -779,19 +774,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and media and reply and check_shortcut_call(kwargs, send_media_group)
return id_ and media and reply
assert check_shortcut_signature(
Message.reply_media_group, Bot.send_media_group, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_media_group, message.bot, 'send_media_group')
assert check_defaults_handling(message.reply_media_group, message.bot)
monkeypatch.setattr(message.bot, 'send_media_group', make_assertion)
assert message.reply_media_group(media='reply_media_group')
assert message.reply_media_group(media='reply_media_group', quote=True)
def test_reply_photo(self, monkeypatch, message):
send_photo = message.bot.send_photo
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
photo = kwargs['photo'] == 'test_photo'
@ -799,19 +794,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and photo and reply and check_shortcut_call(kwargs, send_photo)
return id_ and photo and reply
assert check_shortcut_signature(
Message.reply_photo, Bot.send_photo, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_photo, message.bot, 'send_photo')
assert check_defaults_handling(message.reply_photo, message.bot)
monkeypatch.setattr(message.bot, 'send_photo', make_assertion)
assert message.reply_photo(photo='test_photo')
assert message.reply_photo(photo='test_photo', quote=True)
def test_reply_audio(self, monkeypatch, message):
send_audio = message.bot.send_audio
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
audio = kwargs['audio'] == 'test_audio'
@ -819,19 +814,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and audio and reply and check_shortcut_call(kwargs, send_audio)
return id_ and audio and reply
assert check_shortcut_signature(
Message.reply_audio, Bot.send_audio, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_audio, message.bot, 'send_audio')
assert check_defaults_handling(message.reply_audio, message.bot)
monkeypatch.setattr(message.bot, 'send_audio', make_assertion)
assert message.reply_audio(audio='test_audio')
assert message.reply_audio(audio='test_audio', quote=True)
def test_reply_document(self, monkeypatch, message):
send_document = message.bot.send_document
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
document = kwargs['document'] == 'test_document'
@ -839,19 +834,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and document and reply and check_shortcut_call(kwargs, send_document)
return id_ and document and reply
assert check_shortcut_signature(
Message.reply_document, Bot.send_document, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_document, message.bot, 'send_document')
assert check_defaults_handling(message.reply_document, message.bot)
monkeypatch.setattr(message.bot, 'send_document', make_assertion)
assert message.reply_document(document='test_document')
assert message.reply_document(document='test_document', quote=True)
def test_reply_animation(self, monkeypatch, message):
send_animation = message.bot.send_animation
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
animation = kwargs['animation'] == 'test_animation'
@ -859,19 +854,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and animation and reply and check_shortcut_call(kwargs, send_animation)
return id_ and animation and reply
assert check_shortcut_signature(
Message.reply_animation, Bot.send_animation, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_animation, message.bot, 'send_animation')
assert check_defaults_handling(message.reply_animation, message.bot)
monkeypatch.setattr(message.bot, 'send_animation', make_assertion)
assert message.reply_animation(animation='test_animation')
assert message.reply_animation(animation='test_animation', quote=True)
def test_reply_sticker(self, monkeypatch, message):
send_sticker = message.bot.send_sticker
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
sticker = kwargs['sticker'] == 'test_sticker'
@ -879,19 +874,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and sticker and reply and check_shortcut_call(kwargs, send_sticker)
return id_ and sticker and reply
assert check_shortcut_signature(
Message.reply_sticker, Bot.send_sticker, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_sticker, message.bot, 'send_sticker')
assert check_defaults_handling(message.reply_sticker, message.bot)
monkeypatch.setattr(message.bot, 'send_sticker', make_assertion)
assert message.reply_sticker(sticker='test_sticker')
assert message.reply_sticker(sticker='test_sticker', quote=True)
def test_reply_video(self, monkeypatch, message):
send_video = message.bot.send_video
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
video = kwargs['video'] == 'test_video'
@ -899,19 +894,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and video and reply and check_shortcut_call(kwargs, send_video)
return id_ and video and reply
assert check_shortcut_signature(
Message.reply_video, Bot.send_video, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_video, message.bot, 'send_video')
assert check_defaults_handling(message.reply_video, message.bot)
monkeypatch.setattr(message.bot, 'send_video', make_assertion)
assert message.reply_video(video='test_video')
assert message.reply_video(video='test_video', quote=True)
def test_reply_video_note(self, monkeypatch, message):
send_video_note = message.bot.send_video_note
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
video_note = kwargs['video_note'] == 'test_video_note'
@ -919,19 +914,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and video_note and reply and check_shortcut_call(kwargs, send_video_note)
return id_ and video_note and reply
assert check_shortcut_signature(
Message.reply_video_note, Bot.send_video_note, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_video_note, message.bot, 'send_video_note')
assert check_defaults_handling(message.reply_video_note, message.bot)
monkeypatch.setattr(message.bot, 'send_video_note', make_assertion)
assert message.reply_video_note(video_note='test_video_note')
assert message.reply_video_note(video_note='test_video_note', quote=True)
def test_reply_voice(self, monkeypatch, message):
send_voice = message.bot.send_voice
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
voice = kwargs['voice'] == 'test_voice'
@ -939,19 +934,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and voice and reply and check_shortcut_call(kwargs, send_voice)
return id_ and voice and reply
assert check_shortcut_signature(
Message.reply_voice, Bot.send_voice, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_voice, message.bot, 'send_voice')
assert check_defaults_handling(message.reply_voice, message.bot)
monkeypatch.setattr(message.bot, 'send_voice', make_assertion)
assert message.reply_voice(voice='test_voice')
assert message.reply_voice(voice='test_voice', quote=True)
def test_reply_location(self, monkeypatch, message):
send_location = message.bot.send_location
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
location = kwargs['location'] == 'test_location'
@ -959,19 +954,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and location and reply and check_shortcut_call(kwargs, send_location)
return id_ and location and reply
assert check_shortcut_signature(
Message.reply_location, Bot.send_location, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_location, message.bot, 'send_location')
assert check_defaults_handling(message.reply_location, message.bot)
monkeypatch.setattr(message.bot, 'send_location', make_assertion)
assert message.reply_location(location='test_location')
assert message.reply_location(location='test_location', quote=True)
def test_reply_venue(self, monkeypatch, message):
send_venue = message.bot.send_venue
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
venue = kwargs['venue'] == 'test_venue'
@ -979,19 +974,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and venue and reply and check_shortcut_call(kwargs, send_venue)
return id_ and venue and reply
assert check_shortcut_signature(
Message.reply_venue, Bot.send_venue, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_venue, message.bot, 'send_venue')
assert check_defaults_handling(message.reply_venue, message.bot)
monkeypatch.setattr(message.bot, 'send_venue', make_assertion)
assert message.reply_venue(venue='test_venue')
assert message.reply_venue(venue='test_venue', quote=True)
def test_reply_contact(self, monkeypatch, message):
send_contact = message.bot.send_contact
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
contact = kwargs['contact'] == 'test_contact'
@ -999,19 +994,19 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and contact and reply and check_shortcut_call(kwargs, send_contact)
return id_ and contact and reply
assert check_shortcut_signature(
Message.reply_contact, Bot.send_contact, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_contact, message.bot, 'send_contact')
assert check_defaults_handling(message.reply_contact, message.bot)
monkeypatch.setattr(message.bot, 'send_contact', make_assertion)
assert message.reply_contact(contact='test_contact')
assert message.reply_contact(contact='test_contact', quote=True)
def test_reply_poll(self, monkeypatch, message):
send_poll = message.bot.send_poll
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
question = kwargs['question'] == 'test_poll'
@ -1020,19 +1015,17 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return (
id_ and question and options and reply and check_shortcut_call(kwargs, send_poll)
)
return id_ and question and options and reply
assert check_shortcut_signature(Message.reply_poll, Bot.send_poll, ['chat_id'], ['quote'])
assert check_shortcut_call(message.reply_poll, message.bot, 'send_poll')
assert check_defaults_handling(message.reply_poll, message.bot)
monkeypatch.setattr(message.bot, 'send_poll', make_assertion)
assert message.reply_poll(question='test_poll', options=['1', '2', '3'])
assert message.reply_poll(question='test_poll', quote=True, options=['1', '2', '3'])
def test_reply_dice(self, monkeypatch, message):
send_dice = message.bot.send_dice
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
contact = kwargs['disable_notification'] is True
@ -1040,48 +1033,46 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return id_ and contact and reply and check_shortcut_call(kwargs, send_dice)
return id_ and contact and reply
assert check_shortcut_signature(Message.reply_dice, Bot.send_dice, ['chat_id'], ['quote'])
assert check_shortcut_call(message.reply_dice, message.bot, 'send_dice')
assert check_defaults_handling(message.reply_dice, message.bot)
monkeypatch.setattr(message.bot, 'send_dice', make_assertion)
assert message.reply_dice(disable_notification=True)
assert message.reply_dice(disable_notification=True, quote=True)
def test_reply_action(self, monkeypatch, message: Message):
send_chat_action = message.bot.send_chat_action
def make_assertion(*_, **kwargs):
id_ = kwargs['chat_id'] == message.chat_id
action = kwargs['action'] == ChatAction.TYPING
return id_ and action and check_shortcut_call(kwargs, send_chat_action)
return id_ and action
assert check_shortcut_signature(
Message.reply_chat_action, Bot.send_chat_action, ['chat_id'], []
)
assert check_shortcut_call(message.reply_chat_action, message.bot, 'send_chat_action')
assert check_defaults_handling(message.reply_chat_action, message.bot)
monkeypatch.setattr(message.bot, 'send_chat_action', make_assertion)
assert message.reply_chat_action(action=ChatAction.TYPING)
def test_reply_game(self, monkeypatch, message: Message):
send_game = message.bot.send_game
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == message.chat_id
and kwargs['game_short_name'] == 'test_game'
and check_shortcut_call(kwargs, send_game)
kwargs['chat_id'] == message.chat_id and kwargs['game_short_name'] == 'test_game'
)
assert check_shortcut_signature(Message.reply_game, Bot.send_game, ['chat_id'], ['quote'])
assert check_shortcut_call(message.reply_game, message.bot, 'send_game')
assert check_defaults_handling(message.reply_game, message.bot)
monkeypatch.setattr(message.bot, 'send_game', make_assertion)
assert message.reply_game(game_short_name='test_game')
assert message.reply_game(game_short_name='test_game', quote=True)
def test_reply_invoice(self, monkeypatch, message: Message):
send_invoice = message.bot.send_invoice
def make_assertion(*_, **kwargs):
title = kwargs['title'] == 'title'
description = kwargs['description'] == 'description'
@ -1099,15 +1090,13 @@ class TestMessage:
and currency
and prices
)
return (
kwargs['chat_id'] == message.chat_id
and args
and check_shortcut_call(kwargs, send_invoice)
)
return kwargs['chat_id'] == message.chat_id and args
assert check_shortcut_signature(
Message.reply_invoice, Bot.send_invoice, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.reply_invoice, message.bot, 'send_invoice')
assert check_defaults_handling(message.reply_invoice, message.bot)
monkeypatch.setattr(message.bot, 'send_invoice', make_assertion)
assert message.reply_invoice(
@ -1132,24 +1121,18 @@ class TestMessage:
@pytest.mark.parametrize('disable_notification', [False, True])
def test_forward(self, monkeypatch, message, disable_notification):
forward_message = message.bot.forward_message
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == 123456
from_chat = kwargs['from_chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
notification = kwargs['disable_notification'] == disable_notification
return (
chat_id
and from_chat
and message_id
and notification
and check_shortcut_call(kwargs, forward_message)
)
return chat_id and from_chat and message_id and notification
assert check_shortcut_signature(
Message.forward, Bot.forward_message, ['from_chat_id', 'message_id'], []
)
assert check_shortcut_call(message.forward, message.bot, 'forward_message')
assert check_defaults_handling(message.forward, message.bot)
monkeypatch.setattr(message.bot, 'forward_message', make_assertion)
assert message.forward(123456, disable_notification=disable_notification)
@ -1158,7 +1141,6 @@ class TestMessage:
@pytest.mark.parametrize('disable_notification', [True, False])
def test_copy(self, monkeypatch, message, disable_notification):
keyboard = [[1, 2]]
copy_message = message.bot.copy_message
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == 123456
@ -1169,18 +1151,13 @@ class TestMessage:
reply_markup = kwargs['reply_markup'] is keyboard
else:
reply_markup = True
return (
chat_id
and from_chat
and message_id
and notification
and reply_markup
and check_shortcut_call(kwargs, copy_message)
)
return chat_id and from_chat and message_id and notification and reply_markup
assert check_shortcut_signature(
Message.copy, Bot.copy_message, ['from_chat_id', 'message_id'], []
)
assert check_shortcut_call(message.copy, message.bot, 'copy_message')
assert check_defaults_handling(message.copy, message.bot)
monkeypatch.setattr(message.bot, 'copy_message', make_assertion)
assert message.copy(123456, disable_notification=disable_notification)
@ -1192,7 +1169,6 @@ class TestMessage:
@pytest.mark.parametrize('disable_notification', [True, False])
def test_reply_copy(self, monkeypatch, message, disable_notification):
keyboard = [[1, 2]]
copy_message = message.bot.copy_message
def make_assertion(*_, **kwargs):
chat_id = kwargs['from_chat_id'] == 123456
@ -1207,19 +1183,13 @@ class TestMessage:
reply = kwargs['reply_to_message_id'] == message.message_id
else:
reply = True
return (
chat_id
and from_chat
and message_id
and notification
and reply_markup
and reply
and check_shortcut_call(kwargs, copy_message)
)
return chat_id and from_chat and message_id and notification and reply_markup and reply
assert check_shortcut_signature(
Message.reply_copy, Bot.copy_message, ['chat_id'], ['quote']
)
assert check_shortcut_call(message.copy, message.bot, 'copy_message')
assert check_defaults_handling(message.copy, message.bot)
monkeypatch.setattr(message.bot, 'copy_message', make_assertion)
assert message.reply_copy(123456, 456789, disable_notification=disable_notification)
@ -1238,15 +1208,11 @@ class TestMessage:
)
def test_edit_text(self, monkeypatch, message):
edit_message_text = message.bot.edit_message_text
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
text = kwargs['text'] == 'test'
return (
chat_id and message_id and text and check_shortcut_call(kwargs, edit_message_text)
)
return chat_id and message_id and text
assert check_shortcut_signature(
Message.edit_text,
@ -1254,23 +1220,24 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.edit_text,
message.bot,
'edit_message_text',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.edit_text, message.bot)
monkeypatch.setattr(message.bot, 'edit_message_text', make_assertion)
assert message.edit_text(text='test')
def test_edit_caption(self, monkeypatch, message):
edit_message_caption = message.bot.edit_message_caption
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
caption = kwargs['caption'] == 'new caption'
return (
chat_id
and message_id
and caption
and check_shortcut_call(kwargs, edit_message_caption)
)
return chat_id and message_id and caption
assert check_shortcut_signature(
Message.edit_caption,
@ -1278,23 +1245,24 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.edit_caption,
message.bot,
'edit_message_caption',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.edit_caption, message.bot)
monkeypatch.setattr(message.bot, 'edit_message_caption', make_assertion)
assert message.edit_caption(caption='new caption')
def test_edit_media(self, monkeypatch, message):
edit_message_media = message.bot.edit_message_media
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
media = kwargs['media'] == 'my_media'
return (
chat_id
and message_id
and media
and check_shortcut_call(kwargs, edit_message_media)
)
return chat_id and message_id and media
assert check_shortcut_signature(
Message.edit_media,
@ -1302,23 +1270,24 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.edit_media,
message.bot,
'edit_message_media',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.edit_media, message.bot)
monkeypatch.setattr(message.bot, 'edit_message_media', make_assertion)
assert message.edit_media('my_media')
def test_edit_reply_markup(self, monkeypatch, message):
edit_message_reply_markup = message.bot.edit_message_reply_markup
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
reply_markup = kwargs['reply_markup'] == [['1', '2']]
return (
chat_id
and message_id
and reply_markup
and check_shortcut_call(kwargs, edit_message_reply_markup)
)
return chat_id and message_id and reply_markup
assert check_shortcut_signature(
Message.edit_reply_markup,
@ -1326,25 +1295,25 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.edit_reply_markup,
message.bot,
'edit_message_reply_markup',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.edit_reply_markup, message.bot)
monkeypatch.setattr(message.bot, 'edit_message_reply_markup', make_assertion)
assert message.edit_reply_markup(reply_markup=[['1', '2']])
def test_edit_live_location(self, monkeypatch, message):
edit_message_live_location = message.bot.edit_message_live_location
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
latitude = kwargs['latitude'] == 1
longitude = kwargs['longitude'] == 2
return (
chat_id
and message_id
and longitude
and latitude
and check_shortcut_call(kwargs, edit_message_live_location)
)
return chat_id and message_id and longitude and latitude
assert check_shortcut_signature(
Message.edit_live_location,
@ -1352,19 +1321,23 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.edit_live_location,
message.bot,
'edit_message_live_location',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.edit_live_location, message.bot)
monkeypatch.setattr(message.bot, 'edit_message_live_location', make_assertion)
assert message.edit_live_location(latitude=1, longitude=2)
def test_stop_live_location(self, monkeypatch, message):
stop_message_live_location = message.bot.stop_message_live_location
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
return (
chat_id and message_id and check_shortcut_call(kwargs, stop_message_live_location)
)
return chat_id and message_id
assert check_shortcut_signature(
Message.stop_live_location,
@ -1372,25 +1345,25 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.stop_live_location,
message.bot,
'stop_message_live_location',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.stop_live_location, message.bot)
monkeypatch.setattr(message.bot, 'stop_message_live_location', make_assertion)
assert message.stop_live_location()
def test_set_game_score(self, monkeypatch, message):
set_game_score = message.bot.set_game_score
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
user_id = kwargs['user_id'] == 1
score = kwargs['score'] == 2
return (
chat_id
and message_id
and user_id
and score
and check_shortcut_call(kwargs, set_game_score)
)
return chat_id and message_id and user_id and score
assert check_shortcut_signature(
Message.set_game_score,
@ -1398,23 +1371,24 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.set_game_score,
message.bot,
'set_game_score',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.set_game_score, message.bot)
monkeypatch.setattr(message.bot, 'set_game_score', make_assertion)
assert message.set_game_score(user_id=1, score=2)
def test_get_game_high_scores(self, monkeypatch, message):
get_game_high_scores = message.bot.get_game_high_scores
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
user_id = kwargs['user_id'] == 1
return (
chat_id
and message_id
and user_id
and check_shortcut_call(kwargs, get_game_high_scores)
)
return chat_id and message_id and user_id
assert check_shortcut_signature(
Message.get_game_high_scores,
@ -1422,66 +1396,79 @@ class TestMessage:
['chat_id', 'message_id', 'inline_message_id'],
[],
)
assert check_shortcut_call(
message.get_game_high_scores,
message.bot,
'get_game_high_scores',
skip_params=['inline_message_id'],
shortcut_kwargs=['message_id', 'chat_id'],
)
assert check_defaults_handling(message.get_game_high_scores, message.bot)
monkeypatch.setattr(message.bot, 'get_game_high_scores', make_assertion)
assert message.get_game_high_scores(user_id=1)
def test_delete(self, monkeypatch, message):
delete_message = message.bot.delete_message
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
return chat_id and message_id and check_shortcut_call(kwargs, delete_message)
return chat_id and message_id
assert check_shortcut_signature(
Message.delete, Bot.delete_message, ['chat_id', 'message_id'], []
)
assert check_shortcut_call(message.delete, message.bot, 'delete_message')
assert check_defaults_handling(message.delete, message.bot)
monkeypatch.setattr(message.bot, 'delete_message', make_assertion)
assert message.delete()
def test_stop_poll(self, monkeypatch, message):
stop_poll = message.bot.stop_poll
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
return chat_id and message_id and check_shortcut_call(kwargs, stop_poll)
return chat_id and message_id
assert check_shortcut_signature(
Message.stop_poll, Bot.stop_poll, ['chat_id', 'message_id'], []
)
assert check_shortcut_call(message.stop_poll, message.bot, 'stop_poll')
assert check_defaults_handling(message.stop_poll, message.bot)
monkeypatch.setattr(message.bot, 'stop_poll', make_assertion)
assert message.stop_poll()
def test_pin(self, monkeypatch, message):
pin_chat_message = message.bot.pin_chat_message
def make_assertion(*args, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
return chat_id and message_id and check_shortcut_call(kwargs, pin_chat_message)
return chat_id and message_id
assert check_shortcut_signature(
Message.pin, Bot.pin_chat_message, ['chat_id', 'message_id'], []
)
assert check_shortcut_call(message.pin, message.bot, 'pin_chat_message')
assert check_defaults_handling(message.pin, message.bot)
monkeypatch.setattr(message.bot, 'pin_chat_message', make_assertion)
assert message.pin()
def test_unpin(self, monkeypatch, message):
unpin_chat_message = message.bot.unpin_chat_message
def make_assertion(*args, **kwargs):
chat_id = kwargs['chat_id'] == message.chat_id
message_id = kwargs['message_id'] == message.message_id
return chat_id and message_id and check_shortcut_call(kwargs, unpin_chat_message)
return chat_id and message_id
assert check_shortcut_signature(
Message.unpin, Bot.unpin_chat_message, ['chat_id', 'message_id'], []
)
assert check_shortcut_call(
message.unpin,
message.bot,
'unpin_chat_message',
shortcut_kwargs=['chat_id', 'message_id'],
)
assert check_defaults_handling(message.unpin, message.bot)
monkeypatch.setattr(message.bot, 'unpin_chat_message', make_assertion)
assert message.unpin()

View file

@ -20,26 +20,18 @@ import os
import pytest
def call_pre_commit_hook(hook_id):
__tracebackhide__ = True
return os.system(' '.join(['pre-commit', 'run', hook_id, '--all-files'])) # pragma: no cover
from tests.conftest import env_var_2_bool
@pytest.mark.nocoverage
@pytest.mark.parametrize('hook_id', ('black', 'flake8', 'pylint', 'mypy'))
@pytest.mark.skipif(not os.getenv('TEST_PRE_COMMIT', False), reason='TEST_PRE_COMMIT not enabled')
def test_pre_commit_hook(hook_id):
assert call_pre_commit_hook(hook_id) == 0 # pragma: no cover
@pytest.mark.nocoverage
@pytest.mark.skipif(not os.getenv('TEST_BUILD', False), reason='TEST_BUILD not enabled')
@pytest.mark.skipif(
not env_var_2_bool(os.getenv('TEST_BUILD', False)), reason='TEST_BUILD not enabled'
)
def test_build():
assert os.system('python setup.py bdist_dumb') == 0 # pragma: no cover
@pytest.mark.nocoverage
@pytest.mark.skipif(not os.getenv('TEST_BUILD', False), reason='TEST_BUILD not enabled')
@pytest.mark.skipif(
not env_var_2_bool(os.getenv('TEST_BUILD', False)), reason='TEST_BUILD not enabled'
)
def test_build_raw():
assert os.system('python setup-raw.py bdist_dumb') == 0 # pragma: no cover

82
tests/test_no_passport.py Normal file
View file

@ -0,0 +1,82 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# 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 file tests the case that PTB was installed *without* the optional dependency `passport`.
Currently this only means that cryptography is not installed.
Because imports in pytest are intricate, we just run
pytest -k test_no_passport.py
with the TEST_NO_PASSPORT environment variable set in addition to the regular test suite.
Because actually uninstalling the optional dependencies would lead to errors in the test suite we
just mock the import to raise the expected exception.
Note that a fixture that just does this for every test that needs it is a nice idea, but for some
reason makes test_updater.py hang indefinitely on GitHub Actions (at least when Hinrich tried that)
"""
import os
from importlib import reload
from unittest import mock
import pytest
from telegram import bot
from telegram.passport import credentials
from tests.conftest import env_var_2_bool
TEST_NO_PASSPORT = env_var_2_bool(os.getenv('TEST_NO_PASSPORT', False))
if TEST_NO_PASSPORT:
orig_import = __import__
def import_mock(module_name, *args, **kwargs):
if module_name.startswith('cryptography'):
raise ModuleNotFoundError('We are testing without cryptography here')
return orig_import(module_name, *args, **kwargs)
with mock.patch('builtins.__import__', side_effect=import_mock):
reload(bot)
reload(credentials)
class TestNoPassport:
"""
The monkeypatches simulate cryptography not being installed even when TEST_NO_PASSPORT is
False, though that doesn't test the actual imports
"""
def test_bot_init(self, bot_info, monkeypatch):
if not TEST_NO_PASSPORT:
monkeypatch.setattr(bot, 'CRYPTO_INSTALLED', False)
with pytest.raises(RuntimeError, match='passport'):
bot.Bot(bot_info['token'], private_key=1, private_key_password=2)
def test_credentials_decrypt(self, monkeypatch):
if not TEST_NO_PASSPORT:
monkeypatch.setattr(credentials, 'CRYPTO_INSTALLED', False)
with pytest.raises(RuntimeError, match='passport'):
credentials.decrypt(1, 1, 1)
def test_encrypted_credentials_decrypted_secret(self, monkeypatch):
if not TEST_NO_PASSPORT:
monkeypatch.setattr(credentials, 'CRYPTO_INSTALLED', False)
ec = credentials.EncryptedCredentials('data', 'hash', 'secret')
with pytest.raises(RuntimeError, match='passport'):
ec.decrypted_secret

View file

@ -25,6 +25,7 @@ from bs4 import BeautifulSoup
from telegram.vendor.ptb_urllib3 import urllib3
import telegram
from tests.conftest import env_var_2_bool
IGNORED_OBJECTS = ('ResponseParameters', 'CallbackGame')
IGNORED_PARAMETERS = {
@ -170,6 +171,8 @@ for thing in soup.select('h4 > a.anchor'):
@pytest.mark.parametrize(('method', 'data'), argvalues=argvalues, ids=names)
@pytest.mark.skipif(os.getenv('TEST_OFFICIAL') != 'true', reason='test_official is not enabled')
@pytest.mark.skipif(
not env_var_2_bool(os.getenv('TEST_OFFICIAL')), reason='test_official is not enabled'
)
def test_official(method, data):
method(data)

View file

@ -31,27 +31,12 @@ from telegram import (
TelegramDecryptionError,
)
# Generated using the scope:
# {
# data: [
# {
# type: 'personal_details',
# native_names: true
# },
# {
# type: 'id_document',
# selfie: true,
# translation: true
# },
# {
# type: 'address_document',
# translation: true
# },
# 'address',
# 'email'
# ],
# v: 1
# }
# Note: All classes in telegram.credentials (except EncryptedCredentials) aren't directly tested
# here, although they are implicitly tested. Testing for those classes was too much work and not
# worth it.
RAW_PASSPORT_DATA = {
'credentials': {
'hash': 'qB4hz2LMcXYhglwz6EvXMMyI3PURisWLXl/iCmCXcSk=',

View file

@ -20,7 +20,7 @@
import pytest
from telegram import PassportFile, PassportElementError, Bot, File
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
@pytest.fixture(scope='class')
@ -56,16 +56,14 @@ class TestPassportFile:
assert passport_file_dict['file_date'] == passport_file.file_date
def test_get_file_instance_method(self, monkeypatch, passport_file):
get_file = passport_file.bot.get_file
def make_assertion(*_, **kwargs):
result = kwargs['file_id'] == passport_file.file_id and check_shortcut_call(
kwargs, get_file
)
result = kwargs['file_id'] == passport_file.file_id
# we need to be a bit hacky here, b/c PF.get_file needs Bot.get_file to return a File
return File(file_id=result, file_unique_id=result)
assert check_shortcut_signature(PassportFile.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(passport_file.get_file, passport_file.bot, 'get_file')
assert check_defaults_handling(passport_file.get_file, passport_file.bot)
monkeypatch.setattr(passport_file.bot, 'get_file', make_assertion)
assert passport_file.get_file().file_id == 'True'

View file

@ -25,7 +25,12 @@ from flaky import flaky
from telegram import Sticker, TelegramError, PhotoSize, InputFile, MessageEntity, Bot
from telegram.error import BadRequest
from telegram.utils.helpers import escape_markdown
from tests.conftest import expect_bad_request, check_shortcut_call, check_shortcut_signature
from tests.conftest import (
expect_bad_request,
check_shortcut_call,
check_shortcut_signature,
check_defaults_handling,
)
@pytest.fixture(scope='function')
@ -465,14 +470,14 @@ class TestPhoto:
bot.send_photo(chat_id=chat_id)
def test_get_file_instance_method(self, monkeypatch, photo):
get_file = photo.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == photo.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == photo.file_id
assert check_shortcut_signature(PhotoSize.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(photo.get_file, photo.bot, 'get_file')
assert check_defaults_handling(photo.get_file, photo.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(photo.bot, 'get_file', make_assertion)
assert photo.get_file()
def test_equality(self, photo):

View file

@ -20,7 +20,7 @@
import pytest
from telegram import Update, User, PreCheckoutQuery, OrderInfo, Bot
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='class')
@ -80,16 +80,18 @@ class TestPreCheckoutQuery:
assert pre_checkout_query_dict['order_info'] == pre_checkout_query.order_info.to_dict()
def test_answer(self, monkeypatch, pre_checkout_query):
answer_pre_checkout_query = pre_checkout_query.bot.answer_pre_checkout_query
def make_assertion(*_, **kwargs):
return kwargs[
'pre_checkout_query_id'
] == pre_checkout_query.id and check_shortcut_call(kwargs, answer_pre_checkout_query)
return kwargs['pre_checkout_query_id'] == pre_checkout_query.id
assert check_shortcut_signature(
PreCheckoutQuery.answer, Bot.answer_pre_checkout_query, ['pre_checkout_query_id'], []
)
assert check_shortcut_call(
pre_checkout_query.answer,
pre_checkout_query.bot,
'answer_pre_checkout_query',
)
assert check_defaults_handling(pre_checkout_query.answer, pre_checkout_query.bot)
monkeypatch.setattr(pre_checkout_query.bot, 'answer_pre_checkout_query', make_assertion)
assert pre_checkout_query.answer(ok=True)

View file

@ -20,7 +20,7 @@
import pytest
from telegram import Update, User, ShippingAddress, ShippingQuery, Bot
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='class')
@ -65,16 +65,16 @@ class TestShippingQuery:
assert shipping_query_dict['shipping_address'] == shipping_query.shipping_address.to_dict()
def test_answer(self, monkeypatch, shipping_query):
answer_shipping_query = shipping_query.bot.answer_shipping_query
def make_assertion(*_, **kwargs):
return kwargs['shipping_query_id'] == shipping_query.id and check_shortcut_call(
kwargs, answer_shipping_query
)
return kwargs['shipping_query_id'] == shipping_query.id
assert check_shortcut_signature(
ShippingQuery.answer, Bot.answer_shipping_query, ['shipping_query_id'], []
)
assert check_shortcut_call(
shipping_query.answer, shipping_query.bot, 'answer_shipping_query'
)
assert check_defaults_handling(shipping_query.answer, shipping_query.bot)
monkeypatch.setattr(shipping_query.bot, 'answer_shipping_query', make_assertion)
assert shipping_query.answer(ok=True)

View file

@ -25,7 +25,7 @@ from flaky import flaky
from telegram import Sticker, PhotoSize, TelegramError, StickerSet, Audio, MaskPosition, Bot
from telegram.error import BadRequest
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='function')
@ -505,14 +505,14 @@ class TestStickerSet:
assert test_flag
def test_get_file_instance_method(self, monkeypatch, sticker):
get_file = sticker.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == sticker.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == sticker.file_id
assert check_shortcut_signature(Sticker.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(sticker.get_file, sticker.bot, 'get_file')
assert check_defaults_handling(sticker.get_file, sticker.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(sticker.bot, 'get_file', make_assertion)
assert sticker.get_file()
def test_equality(self):

View file

@ -111,6 +111,7 @@ class TestUpdater:
self.err_handler_called.clear()
self.err_handler_called.wait()
@pytest.mark.filterwarnings('ignore:.*:pytest.PytestUnhandledThreadExceptionWarning')
def test_get_updates_bailout_err(self, monkeypatch, updater, caplog):
error = InvalidToken()

View file

@ -20,7 +20,7 @@ import pytest
from telegram import Update, User, Bot
from telegram.utils.helpers import escape_markdown
from tests.conftest import check_shortcut_signature, check_shortcut_call
from tests.conftest import check_shortcut_signature, check_shortcut_call, check_defaults_handling
@pytest.fixture(scope='function')
@ -129,197 +129,159 @@ class TestUser:
assert user.link is None
def test_instance_method_get_profile_photos(self, monkeypatch, user):
get_profile_photos = user.bot.get_user_profile_photos
def make_assertion(*_, **kwargs):
return kwargs['user_id'] == user.id and check_shortcut_call(kwargs, get_profile_photos)
return kwargs['user_id'] == user.id
assert check_shortcut_signature(
User.get_profile_photos, Bot.get_user_profile_photos, ['user_id'], []
)
assert check_shortcut_call(user.get_profile_photos, user.bot, 'get_user_profile_photos')
assert check_defaults_handling(user.get_profile_photos, user.bot)
monkeypatch.setattr(user.bot, 'get_user_profile_photos', make_assertion)
assert user.get_profile_photos()
def test_instance_method_pin_message(self, monkeypatch, user):
pin_message = user.bot.pin_chat_message
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == user.id and check_shortcut_call(kwargs, pin_message)
return kwargs['chat_id'] == user.id
assert check_shortcut_signature(User.pin_message, Bot.pin_chat_message, ['chat_id'], [])
assert check_shortcut_call(user.pin_message, user.bot, 'pin_chat_message')
assert check_defaults_handling(user.pin_message, user.bot)
monkeypatch.setattr(user.bot, 'pin_chat_message', make_assertion)
assert user.pin_message(1)
def test_instance_method_unpin_message(self, monkeypatch, user):
unpin_message = user.bot.unpin_chat_message
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == user.id and check_shortcut_call(kwargs, unpin_message)
return kwargs['chat_id'] == user.id
assert check_shortcut_signature(
User.unpin_message, Bot.unpin_chat_message, ['chat_id'], []
)
assert check_shortcut_call(user.unpin_message, user.bot, 'unpin_chat_message')
assert check_defaults_handling(user.unpin_message, user.bot)
monkeypatch.setattr(user.bot, 'unpin_chat_message', make_assertion)
assert user.unpin_message()
def test_instance_method_unpin_all_messages(self, monkeypatch, user):
unpin_all_messages = user.bot.unpin_all_chat_messages
def make_assertion(*_, **kwargs):
return kwargs['chat_id'] == user.id and check_shortcut_call(kwargs, unpin_all_messages)
return kwargs['chat_id'] == user.id
assert check_shortcut_signature(
User.unpin_all_messages, Bot.unpin_all_chat_messages, ['chat_id'], []
)
assert check_shortcut_call(user.unpin_all_messages, user.bot, 'unpin_all_chat_messages')
assert check_defaults_handling(user.unpin_all_messages, user.bot)
monkeypatch.setattr(user.bot, 'unpin_all_chat_messages', make_assertion)
assert user.unpin_all_messages()
def test_instance_method_send_message(self, monkeypatch, user):
send_message = user.bot.send_message
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['text'] == 'test'
and check_shortcut_call(kwargs, send_message)
)
return kwargs['chat_id'] == user.id and kwargs['text'] == 'test'
assert check_shortcut_signature(User.send_message, Bot.send_message, ['chat_id'], [])
assert check_shortcut_call(user.send_message, user.bot, 'send_message')
assert check_defaults_handling(user.send_message, user.bot)
monkeypatch.setattr(user.bot, 'send_message', make_assertion)
assert user.send_message('test')
def test_instance_method_send_photo(self, monkeypatch, user):
send_photo = user.bot.send_photo
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['photo'] == 'test_photo'
and check_shortcut_call(kwargs, send_photo)
)
return kwargs['chat_id'] == user.id and kwargs['photo'] == 'test_photo'
assert check_shortcut_signature(User.send_photo, Bot.send_photo, ['chat_id'], [])
assert check_shortcut_call(user.send_photo, user.bot, 'send_photo')
assert check_defaults_handling(user.send_photo, user.bot)
monkeypatch.setattr(user.bot, 'send_photo', make_assertion)
assert user.send_photo('test_photo')
def test_instance_method_send_media_group(self, monkeypatch, user):
send_media_group = user.bot.send_media_group
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['media'] == 'test_media_group'
and check_shortcut_call(kwargs, send_media_group)
)
return kwargs['chat_id'] == user.id and kwargs['media'] == 'test_media_group'
assert check_shortcut_signature(
User.send_media_group, Bot.send_media_group, ['chat_id'], []
)
assert check_shortcut_call(user.send_media_group, user.bot, 'send_media_group')
assert check_defaults_handling(user.send_media_group, user.bot)
monkeypatch.setattr(user.bot, 'send_media_group', make_assertion)
assert user.send_media_group('test_media_group')
def test_instance_method_send_audio(self, monkeypatch, user):
send_audio = user.bot.send_audio
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['audio'] == 'test_audio'
and check_shortcut_call(kwargs, send_audio)
)
return kwargs['chat_id'] == user.id and kwargs['audio'] == 'test_audio'
assert check_shortcut_signature(User.send_audio, Bot.send_audio, ['chat_id'], [])
assert check_shortcut_call(user.send_audio, user.bot, 'send_audio')
assert check_defaults_handling(user.send_audio, user.bot)
monkeypatch.setattr(user.bot, 'send_audio', make_assertion)
assert user.send_audio('test_audio')
def test_instance_method_send_chat_action(self, monkeypatch, user):
send_chat_action = user.bot.send_chat_action
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['action'] == 'test_chat_action'
and check_shortcut_call(kwargs, send_chat_action)
)
return kwargs['chat_id'] == user.id and kwargs['action'] == 'test_chat_action'
assert check_shortcut_signature(
User.send_chat_action, Bot.send_chat_action, ['chat_id'], []
)
assert check_shortcut_call(user.send_chat_action, user.bot, 'send_chat_action')
assert check_defaults_handling(user.send_chat_action, user.bot)
monkeypatch.setattr(user.bot, 'send_chat_action', make_assertion)
assert user.send_chat_action('test_chat_action')
def test_instance_method_send_contact(self, monkeypatch, user):
send_contact = user.bot.send_contact
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['phone_number'] == 'test_contact'
and check_shortcut_call(kwargs, send_contact)
)
return kwargs['chat_id'] == user.id and kwargs['phone_number'] == 'test_contact'
assert check_shortcut_signature(User.send_contact, Bot.send_contact, ['chat_id'], [])
assert check_shortcut_call(user.send_contact, user.bot, 'send_contact')
assert check_defaults_handling(user.send_contact, user.bot)
monkeypatch.setattr(user.bot, 'send_contact', make_assertion)
assert user.send_contact(phone_number='test_contact')
def test_instance_method_send_dice(self, monkeypatch, user):
send_dice = user.bot.send_dice
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['emoji'] == 'test_dice'
and check_shortcut_call(kwargs, send_dice)
)
return kwargs['chat_id'] == user.id and kwargs['emoji'] == 'test_dice'
assert check_shortcut_signature(User.send_dice, Bot.send_dice, ['chat_id'], [])
assert check_shortcut_call(user.send_dice, user.bot, 'send_dice')
assert check_defaults_handling(user.send_dice, user.bot)
monkeypatch.setattr(user.bot, 'send_dice', make_assertion)
assert user.send_dice(emoji='test_dice')
def test_instance_method_send_document(self, monkeypatch, user):
send_document = user.bot.send_document
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['document'] == 'test_document'
and check_shortcut_call(kwargs, send_document)
)
return kwargs['chat_id'] == user.id and kwargs['document'] == 'test_document'
assert check_shortcut_signature(User.send_document, Bot.send_document, ['chat_id'], [])
assert check_shortcut_call(user.send_document, user.bot, 'send_document')
assert check_defaults_handling(user.send_document, user.bot)
monkeypatch.setattr(user.bot, 'send_document', make_assertion)
assert user.send_document('test_document')
def test_instance_method_send_game(self, monkeypatch, user):
send_game = user.bot.send_game
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['game_short_name'] == 'test_game'
and check_shortcut_call(kwargs, send_game)
)
return kwargs['chat_id'] == user.id and kwargs['game_short_name'] == 'test_game'
assert check_shortcut_signature(User.send_game, Bot.send_game, ['chat_id'], [])
assert check_shortcut_call(user.send_game, user.bot, 'send_game')
assert check_defaults_handling(user.send_game, user.bot)
monkeypatch.setattr(user.bot, 'send_game', make_assertion)
assert user.send_game(game_short_name='test_game')
def test_instance_method_send_invoice(self, monkeypatch, user):
send_invoice = user.bot.send_invoice
def make_assertion(*_, **kwargs):
title = kwargs['title'] == 'title'
description = kwargs['description'] == 'description'
@ -337,11 +299,11 @@ class TestUser:
and currency
and prices
)
return (
kwargs['chat_id'] == user.id and args and check_shortcut_call(kwargs, send_invoice)
)
return kwargs['chat_id'] == user.id and args
assert check_shortcut_signature(User.send_invoice, Bot.send_invoice, ['chat_id'], [])
assert check_shortcut_call(user.send_invoice, user.bot, 'send_invoice')
assert check_defaults_handling(user.send_invoice, user.bot)
monkeypatch.setattr(user.bot, 'send_invoice', make_assertion)
assert user.send_invoice(
@ -355,151 +317,117 @@ class TestUser:
)
def test_instance_method_send_location(self, monkeypatch, user):
send_location = user.bot.send_location
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['latitude'] == 'test_location'
and check_shortcut_call(kwargs, send_location)
)
return kwargs['chat_id'] == user.id and kwargs['latitude'] == 'test_location'
assert check_shortcut_signature(User.send_location, Bot.send_location, ['chat_id'], [])
assert check_shortcut_call(user.send_location, user.bot, 'send_location')
assert check_defaults_handling(user.send_location, user.bot)
monkeypatch.setattr(user.bot, 'send_location', make_assertion)
assert user.send_location('test_location')
def test_instance_method_send_sticker(self, monkeypatch, user):
send_sticker = user.bot.send_sticker
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['sticker'] == 'test_sticker'
and check_shortcut_call(kwargs, send_sticker)
)
return kwargs['chat_id'] == user.id and kwargs['sticker'] == 'test_sticker'
assert check_shortcut_signature(User.send_sticker, Bot.send_sticker, ['chat_id'], [])
assert check_shortcut_call(user.send_sticker, user.bot, 'send_sticker')
assert check_defaults_handling(user.send_sticker, user.bot)
monkeypatch.setattr(user.bot, 'send_sticker', make_assertion)
assert user.send_sticker('test_sticker')
def test_instance_method_send_video(self, monkeypatch, user):
send_video = user.bot.send_video
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['video'] == 'test_video'
and check_shortcut_call(kwargs, send_video)
)
return kwargs['chat_id'] == user.id and kwargs['video'] == 'test_video'
assert check_shortcut_signature(User.send_video, Bot.send_video, ['chat_id'], [])
assert check_shortcut_call(user.send_video, user.bot, 'send_video')
assert check_defaults_handling(user.send_video, user.bot)
monkeypatch.setattr(user.bot, 'send_video', make_assertion)
assert user.send_video('test_video')
def test_instance_method_send_venue(self, monkeypatch, user):
send_venue = user.bot.send_venue
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['title'] == 'test_venue'
and check_shortcut_call(kwargs, send_venue)
)
return kwargs['chat_id'] == user.id and kwargs['title'] == 'test_venue'
assert check_shortcut_signature(User.send_venue, Bot.send_venue, ['chat_id'], [])
assert check_shortcut_call(user.send_venue, user.bot, 'send_venue')
assert check_defaults_handling(user.send_venue, user.bot)
monkeypatch.setattr(user.bot, 'send_venue', make_assertion)
assert user.send_venue(title='test_venue')
def test_instance_method_send_video_note(self, monkeypatch, user):
send_video_note = user.bot.send_video_note
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['video_note'] == 'test_video_note'
and check_shortcut_call(kwargs, send_video_note)
)
return kwargs['chat_id'] == user.id and kwargs['video_note'] == 'test_video_note'
assert check_shortcut_signature(User.send_video_note, Bot.send_video_note, ['chat_id'], [])
assert check_shortcut_call(user.send_video_note, user.bot, 'send_video_note')
assert check_defaults_handling(user.send_video_note, user.bot)
monkeypatch.setattr(user.bot, 'send_video_note', make_assertion)
assert user.send_video_note('test_video_note')
def test_instance_method_send_voice(self, monkeypatch, user):
send_voice = user.bot.send_voice
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['voice'] == 'test_voice'
and check_shortcut_call(kwargs, send_voice)
)
return kwargs['chat_id'] == user.id and kwargs['voice'] == 'test_voice'
assert check_shortcut_signature(User.send_voice, Bot.send_voice, ['chat_id'], [])
assert check_shortcut_call(user.send_voice, user.bot, 'send_voice')
assert check_defaults_handling(user.send_voice, user.bot)
monkeypatch.setattr(user.bot, 'send_voice', make_assertion)
assert user.send_voice('test_voice')
def test_instance_method_send_animation(self, monkeypatch, user):
send_animation = user.bot.send_animation
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['animation'] == 'test_animation'
and check_shortcut_call(kwargs, send_animation)
)
return kwargs['chat_id'] == user.id and kwargs['animation'] == 'test_animation'
assert check_shortcut_signature(User.send_animation, Bot.send_animation, ['chat_id'], [])
assert check_shortcut_call(user.send_animation, user.bot, 'send_animation')
assert check_defaults_handling(user.send_animation, user.bot)
monkeypatch.setattr(user.bot, 'send_animation', make_assertion)
assert user.send_animation('test_animation')
def test_instance_method_send_poll(self, monkeypatch, user):
send_poll = user.bot.send_poll
def make_assertion(*_, **kwargs):
return (
kwargs['chat_id'] == user.id
and kwargs['question'] == 'test_poll'
and check_shortcut_call(kwargs, send_poll)
)
return kwargs['chat_id'] == user.id and kwargs['question'] == 'test_poll'
assert check_shortcut_signature(User.send_poll, Bot.send_poll, ['chat_id'], [])
assert check_shortcut_call(user.send_poll, user.bot, 'send_poll')
assert check_defaults_handling(user.send_poll, user.bot)
monkeypatch.setattr(user.bot, 'send_poll', make_assertion)
assert user.send_poll(question='test_poll', options=[1, 2])
def test_instance_method_send_copy(self, monkeypatch, user):
send_copy = user.bot.copy_message
def make_assertion(*_, **kwargs):
user_id = kwargs['chat_id'] == user.id
message_id = kwargs['message_id'] == 'message_id'
from_chat_id = kwargs['from_chat_id'] == 'from_chat_id'
return (
from_chat_id and message_id and user_id and check_shortcut_call(kwargs, send_copy)
)
return from_chat_id and message_id and user_id
assert check_shortcut_signature(User.send_copy, Bot.copy_message, ['chat_id'], [])
assert check_shortcut_call(user.copy_message, user.bot, 'copy_message')
assert check_defaults_handling(user.copy_message, user.bot)
monkeypatch.setattr(user.bot, 'copy_message', make_assertion)
assert user.send_copy(from_chat_id='from_chat_id', message_id='message_id')
def test_instance_method_copy_message(self, monkeypatch, user):
copy_message = user.bot.copy_message
def make_assertion(*_, **kwargs):
chat_id = kwargs['chat_id'] == 'chat_id'
message_id = kwargs['message_id'] == 'message_id'
user_id = kwargs['from_chat_id'] == user.id
return chat_id and message_id and user_id and check_shortcut_call(kwargs, copy_message)
return chat_id and message_id and user_id
assert check_shortcut_signature(User.copy_message, Bot.copy_message, ['from_chat_id'], [])
assert check_shortcut_call(user.copy_message, user.bot, 'copy_message')
assert check_defaults_handling(user.copy_message, user.bot)
monkeypatch.setattr(user.bot, 'copy_message', make_assertion)
assert user.copy_message(chat_id='chat_id', message_id='message_id')

View file

@ -25,7 +25,7 @@ from flaky import flaky
from telegram import Video, TelegramError, Voice, PhotoSize, MessageEntity, Bot
from telegram.error import BadRequest
from telegram.utils.helpers import escape_markdown
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='function')
@ -330,14 +330,14 @@ class TestVideo:
bot.send_video(chat_id=chat_id)
def test_get_file_instance_method(self, monkeypatch, video):
get_file = video.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == video.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == video.file_id
assert check_shortcut_signature(Video.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(video.get_file, video.bot, 'get_file')
assert check_defaults_handling(video.get_file, video.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(video.bot, 'get_file', make_assertion)
assert video.get_file()
def test_equality(self, video):

View file

@ -24,7 +24,7 @@ from flaky import flaky
from telegram import VideoNote, TelegramError, Voice, PhotoSize, Bot
from telegram.error import BadRequest
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='function')
@ -228,16 +228,14 @@ class TestVideoNote:
bot.send_video_note(chat_id=chat_id)
def test_get_file_instance_method(self, monkeypatch, video_note):
get_file = video_note.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == video_note.file_id and check_shortcut_call(
kwargs, get_file
)
return kwargs['file_id'] == video_note.file_id
assert check_shortcut_signature(VideoNote.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(video_note.get_file, video_note.bot, 'get_file')
assert check_defaults_handling(video_note.get_file, video_note.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(video_note.bot, 'get_file', make_assertion)
assert video_note.get_file()
def test_equality(self, video_note):

View file

@ -25,7 +25,7 @@ from flaky import flaky
from telegram import Audio, Voice, TelegramError, MessageEntity, Bot
from telegram.error import BadRequest
from telegram.utils.helpers import escape_markdown
from tests.conftest import check_shortcut_call, check_shortcut_signature
from tests.conftest import check_shortcut_call, check_shortcut_signature, check_defaults_handling
@pytest.fixture(scope='function')
@ -284,14 +284,14 @@ class TestVoice:
bot.sendVoice(chat_id)
def test_get_file_instance_method(self, monkeypatch, voice):
get_file = voice.bot.get_file
def make_assertion(*_, **kwargs):
return kwargs['file_id'] == voice.file_id and check_shortcut_call(kwargs, get_file)
return kwargs['file_id'] == voice.file_id
assert check_shortcut_signature(Voice.get_file, Bot.get_file, ['file_id'], [])
assert check_shortcut_call(voice.get_file, voice.bot, 'get_file')
assert check_defaults_handling(voice.get_file, voice.bot)
monkeypatch.setattr('telegram.Bot.get_file', make_assertion)
monkeypatch.setattr(voice.bot, 'get_file', make_assertion)
assert voice.get_file()
def test_equality(self, voice):