Refactor MRO of InputMedia* and Some File-Like Classes (#2717)

This commit is contained in:
eldbud 2021-10-15 19:03:56 +03:00 committed by Hinrich Mahler
parent 59014bee64
commit 7e51901d51
23 changed files with 411 additions and 524 deletions

View file

@ -3,6 +3,9 @@
telegram.Animation
==================
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.Animation
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -3,6 +3,9 @@
telegram.Audio
==============
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.Audio
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -2,7 +2,9 @@
telegram.Document
=================
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.Document
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -2,7 +2,9 @@
telegram.PhotoSize
==================
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.PhotoSize
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -3,6 +3,9 @@
telegram.Sticker
================
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.Sticker
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -3,6 +3,9 @@
telegram.Video
==============
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.Video
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -3,6 +3,9 @@
telegram.VideoNote
==================
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.VideoNote
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -3,6 +3,9 @@
telegram.Voice
==============
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. autoclass:: telegram.Voice
:members:
:show-inheritance:
:inherited-members: TelegramObject

View file

@ -223,9 +223,7 @@ class Bot(TelegramObject):
for key, val in data.items():
# 1)
if isinstance(val, InputMedia):
val.parse_mode = DefaultValue.get_value( # type: ignore[attr-defined]
val.parse_mode # type: ignore[attr-defined]
)
val.parse_mode = DefaultValue.get_value(val.parse_mode)
elif key == 'media' and isinstance(val, list):
for media in val:
media.parse_mode = DefaultValue.get_value(media.parse_mode)

View file

@ -0,0 +1,82 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-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/].
"""Common base class for media objects"""
from typing import TYPE_CHECKING
from telegram import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
class _BaseMedium(TelegramObject):
"""Base class for objects representing the various media file types.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`, optional): File size.
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
__slots__ = ('bot', 'file_id', 'file_size', 'file_unique_id')
def __init__(
self, file_id: str, file_unique_id: str, file_size: int = None, bot: 'Bot' = None
):
# Required
self.file_id: str = str(file_id)
self.file_unique_id = str(file_unique_id)
# Optionals
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)

View file

@ -0,0 +1,85 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-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/].
"""Common base class for media objects with thumbnails"""
from typing import TYPE_CHECKING, TypeVar, Type, Optional
from telegram import PhotoSize
from telegram._files._basemedium import _BaseMedium
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
ThumbedMT = TypeVar('ThumbedMT', bound='_BaseThumbedMedium', covariant=True)
class _BaseThumbedMedium(_BaseMedium):
"""Base class for objects representing the various media file types that may include a
thumbnail.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`, optional): File size.
thumb (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by sender.
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`): Optional. File size.
thumb (:class:`telegram.PhotoSize`): Optional. Thumbnail as defined by sender.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
__slots__ = ('thumb',)
def __init__(
self,
file_id: str,
file_unique_id: str,
file_size: int = None,
thumb: PhotoSize = None,
bot: 'Bot' = None,
):
super().__init__(
file_id=file_id, file_unique_id=file_unique_id, file_size=file_size, bot=bot
)
self.thumb = thumb
@classmethod
def de_json(cls: Type[ThumbedMT], data: Optional[JSONDict], bot: 'Bot') -> Optional[ThumbedMT]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
return cls(bot=bot, **data)

View file

@ -17,17 +17,16 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Animation."""
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any
from telegram import PhotoSize, TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram import PhotoSize
from telegram._files._basethumbedmedium import _BaseThumbedMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class Animation(TelegramObject):
class Animation(_BaseThumbedMedium):
"""This object represents an animation file (GIF or H.264/MPEG-4 AVC video without sound).
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -65,18 +64,7 @@ class Animation(TelegramObject):
"""
__slots__ = (
'bot',
'width',
'file_id',
'file_size',
'file_name',
'thumb',
'duration',
'mime_type',
'height',
'file_unique_id',
)
__slots__ = ('duration', 'height', 'file_name', 'mime_type', 'width')
def __init__(
self,
@ -92,45 +80,17 @@ class Animation(TelegramObject):
bot: 'Bot' = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
bot=bot,
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.width = int(width)
self.height = int(height)
self.duration = duration
# Optionals
self.thumb = thumb
self.file_name = file_name
# Optional
self.mime_type = mime_type
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['Animation']:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
return cls(bot=bot, **data)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
self.file_name = file_name

View file

@ -18,17 +18,16 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Audio."""
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any
from telegram import PhotoSize, TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram import PhotoSize
from telegram._files._basethumbedmedium import _BaseThumbedMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class Audio(TelegramObject):
class Audio(_BaseThumbedMedium):
"""This object represents an audio file to be treated as music by the Telegram clients.
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -69,18 +68,7 @@ class Audio(TelegramObject):
"""
__slots__ = (
'file_id',
'bot',
'file_size',
'file_name',
'thumb',
'title',
'duration',
'performer',
'mime_type',
'file_unique_id',
)
__slots__ = ('duration', 'file_name', 'mime_type', 'performer', 'title')
def __init__(
self,
@ -96,45 +84,17 @@ class Audio(TelegramObject):
file_name: str = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
bot=bot,
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.duration = int(duration)
# Optionals
self.duration = duration
# Optional
self.performer = performer
self.title = title
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
self.thumb = thumb
self.bot = bot
self._id_attrs = (self.file_unique_id,)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['Audio']:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
return cls(bot=bot, **data)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
self.file_name = file_name

View file

@ -18,17 +18,16 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Document."""
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any
from telegram import PhotoSize, TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram import PhotoSize
from telegram._files._basethumbedmedium import _BaseThumbedMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class Document(TelegramObject):
class Document(_BaseThumbedMedium):
"""This object represents a general file
(as opposed to photos, voice messages and audio files).
@ -60,15 +59,7 @@ class Document(TelegramObject):
"""
__slots__ = (
'bot',
'file_id',
'file_size',
'file_name',
'thumb',
'mime_type',
'file_unique_id',
)
__slots__ = ('file_name', 'mime_type')
def __init__(
self,
@ -81,42 +72,13 @@ class Document(TelegramObject):
bot: 'Bot' = None,
**_kwargs: Any,
):
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
# Optionals
self.thumb = thumb
self.file_name = file_name
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
bot=bot,
)
# Optional
self.mime_type = mime_type
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['Document']:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
return cls(bot=bot, **data)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
self.file_name = file_name

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""Base class for Telegram InputMedia Objects."""
from typing import Union, List, Tuple
from typing import Union, List, Tuple, Optional
from telegram import (
Animation,
@ -34,18 +34,59 @@ from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.files import parse_file_input
from telegram._utils.types import FileInput, JSONDict, ODVInput
MediaType = Union[Animation, Audio, Document, PhotoSize, Video]
class InputMedia(TelegramObject):
"""Base class for Telegram InputMedia Objects.
"""
Base class for Telegram InputMedia Objects.
See :class:`telegram.InputMediaAnimation`, :class:`telegram.InputMediaAudio`,
:class:`telegram.InputMediaDocument`, :class:`telegram.InputMediaPhoto` and
:class:`telegram.InputMediaVideo` for detailed use.
.. versionchanged:: 14.0:
Added arguments and attributes :attr:`media_type`, :attr:`media`, :attr:`caption`,
:attr:`caption_entities`, :attr:`parse_mode`.
Args:
media_type (:obj:`str`) Type of media that the instance represents.
media (:obj:`str` | `filelike object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation` | :class:`telegram.Audio` | \
:class:`telegram.Document` | :class:`telegram.PhotoSize` | \
:class:`telegram.Video`):
File to send. Pass a file_id to send a file that exists on the Telegram servers
(recommended), pass an HTTP URL for Telegram to get a file from the Internet.
Lastly you can pass an existing telegram media object of the corresponding type
to send.
caption (:obj:`str`, optional): Caption of the media to be sent, 0-1024 characters
after entities parsing.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
Attributes:
type (:obj:`str`): Type of the input media.
media (:obj:`str` | :class:`telegram.InputFile`): Media to send.
caption (:obj:`str`): Optional. Caption of the media to be sent.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
caption_entities (List[:class:`telegram.MessageEntity`]): Optional. List of special
entities that appear in the caption.
"""
__slots__ = ()
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...], None] = None
__slots__ = ('caption', 'caption_entities', 'media', 'parse_mode', 'type')
def __init__(
self,
media_type: str,
media: Union[str, InputFile, MediaType],
caption: str = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
):
self.type = media_type
self.media = media
self.caption = caption
self.caption_entities = caption_entities
self.parse_mode = parse_mode
def to_dict(self) -> JSONDict:
"""See :meth:`telegram.TelegramObject.to_dict`."""
@ -58,6 +99,10 @@ class InputMedia(TelegramObject):
return data
@staticmethod
def _parse_thumb_input(thumb: Optional[FileInput]) -> Optional[Union[str, InputFile]]:
return parse_file_input(thumb, attach=True) if thumb is not None else thumb
class InputMediaAnimation(InputMedia):
"""Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
@ -102,7 +147,7 @@ class InputMediaAnimation(InputMedia):
duration (:obj:`int`, optional): Animation duration.
Attributes:
type (:obj:`str`): ``animation``.
type (:obj:`str`): ``'animation'``.
media (:obj:`str` | :class:`telegram.InputFile`): Animation to send.
caption (:obj:`str`): Optional. Caption of the document to be sent.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
@ -115,17 +160,7 @@ class InputMediaAnimation(InputMedia):
"""
__slots__ = (
'caption_entities',
'width',
'media',
'thumb',
'caption',
'duration',
'parse_mode',
'height',
'type',
)
__slots__ = ('duration', 'height', 'thumb', 'width')
def __init__(
self,
@ -139,28 +174,18 @@ class InputMediaAnimation(InputMedia):
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'animation'
if isinstance(media, Animation):
self.media: Union[str, InputFile] = media.file_id
self.width = media.width
self.height = media.height
self.duration = media.duration
width = media.width if width is None else width
height = media.height if height is None else height
duration = media.duration if duration is None else duration
media = media.file_id
else:
self.media = parse_file_input(media, attach=True, filename=filename)
media = parse_file_input(media, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
if caption:
self.caption = caption
self.parse_mode = parse_mode
self.caption_entities = caption_entities
if width:
super().__init__('animation', media, caption, caption_entities, parse_mode)
self.thumb = self._parse_thumb_input(thumb)
self.width = width
if height:
self.height = height
if duration:
self.duration = duration
@ -190,7 +215,7 @@ class InputMediaPhoto(InputMedia):
entities that appear in the caption, which can be specified instead of parse_mode.
Attributes:
type (:obj:`str`): ``photo``.
type (:obj:`str`): ``'photo'``.
media (:obj:`str` | :class:`telegram.InputFile`): Photo to send.
caption (:obj:`str`): Optional. Caption of the document to be sent.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
@ -199,7 +224,7 @@ class InputMediaPhoto(InputMedia):
"""
__slots__ = ('caption_entities', 'media', 'caption', 'parse_mode', 'type')
__slots__ = ()
def __init__(
self,
@ -209,13 +234,8 @@ class InputMediaPhoto(InputMedia):
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'photo'
self.media = parse_file_input(media, PhotoSize, attach=True, filename=filename)
if caption:
self.caption = caption
self.parse_mode = parse_mode
self.caption_entities = caption_entities
media = parse_file_input(media, PhotoSize, attach=True, filename=filename)
super().__init__('photo', media, caption, caption_entities, parse_mode)
class InputMediaVideo(InputMedia):
@ -226,7 +246,7 @@ class InputMediaVideo(InputMedia):
width, height and duration from that video, unless otherwise specified with the optional
arguments.
* ``thumb`` will be ignored for small video files, for which Telegram can easily
generate thumb nails. However, this behaviour is undocumented and might be changed
generate thumbnails. However, this behaviour is undocumented and might be changed
by Telegram.
Args:
@ -266,7 +286,7 @@ class InputMediaVideo(InputMedia):
Accept :obj:`bytes` as input.
Attributes:
type (:obj:`str`): ``video``.
type (:obj:`str`): ``'video'``.
media (:obj:`str` | :class:`telegram.InputFile`): Video file to send.
caption (:obj:`str`): Optional. Caption of the document to be sent.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
@ -281,18 +301,7 @@ class InputMediaVideo(InputMedia):
"""
__slots__ = (
'caption_entities',
'width',
'media',
'thumb',
'supports_streaming',
'caption',
'duration',
'parse_mode',
'height',
'type',
)
__slots__ = ('duration', 'height', 'thumb', 'supports_streaming', 'width')
def __init__(
self,
@ -307,30 +316,20 @@ class InputMediaVideo(InputMedia):
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'video'
if isinstance(media, Video):
self.media: Union[str, InputFile] = media.file_id
self.width = media.width
self.height = media.height
self.duration = media.duration
width = width if width is not None else media.width
height = height if height is not None else media.height
duration = duration if duration is not None else media.duration
media = media.file_id
else:
self.media = parse_file_input(media, attach=True, filename=filename)
media = parse_file_input(media, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
if caption:
self.caption = caption
self.parse_mode = parse_mode
self.caption_entities = caption_entities
if width:
super().__init__('video', media, caption, caption_entities, parse_mode)
self.width = width
if height:
self.height = height
if duration:
self.duration = duration
if supports_streaming:
self.thumb = self._parse_thumb_input(thumb)
self.supports_streaming = supports_streaming
@ -379,7 +378,7 @@ class InputMediaAudio(InputMedia):
Accept :obj:`bytes` as input.
Attributes:
type (:obj:`str`): ``audio``.
type (:obj:`str`): ``'audio'``.
media (:obj:`str` | :class:`telegram.InputFile`): Audio file to send.
caption (:obj:`str`): Optional. Caption of the document to be sent.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
@ -393,17 +392,7 @@ class InputMediaAudio(InputMedia):
"""
__slots__ = (
'caption_entities',
'media',
'thumb',
'caption',
'title',
'duration',
'type',
'parse_mode',
'performer',
)
__slots__ = ('duration', 'performer', 'thumb', 'title')
def __init__(
self,
@ -417,29 +406,19 @@ class InputMediaAudio(InputMedia):
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'audio'
if isinstance(media, Audio):
self.media: Union[str, InputFile] = media.file_id
self.duration = media.duration
self.performer = media.performer
self.title = media.title
duration = media.duration if duration is None else duration
performer = media.performer if performer is None else performer
title = media.title if title is None else title
media = media.file_id
else:
self.media = parse_file_input(media, attach=True, filename=filename)
media = parse_file_input(media, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
if caption:
self.caption = caption
self.parse_mode = parse_mode
self.caption_entities = caption_entities
if duration:
super().__init__('audio', media, caption, caption_entities, parse_mode)
self.thumb = self._parse_thumb_input(thumb)
self.duration = duration
if performer:
self.performer = performer
if title:
self.title = title
self.performer = performer
class InputMediaDocument(InputMedia):
@ -480,7 +459,7 @@ class InputMediaDocument(InputMedia):
the document is sent as part of an album.
Attributes:
type (:obj:`str`): ``document``.
type (:obj:`str`): ``'document'``.
media (:obj:`str` | :class:`telegram.InputFile`): File to send.
caption (:obj:`str`): Optional. Caption of the document to be sent.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
@ -493,15 +472,7 @@ class InputMediaDocument(InputMedia):
"""
__slots__ = (
'caption_entities',
'media',
'thumb',
'caption',
'parse_mode',
'type',
'disable_content_type_detection',
)
__slots__ = ('disable_content_type_detection', 'thumb')
def __init__(
self,
@ -513,14 +484,7 @@ class InputMediaDocument(InputMedia):
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'document'
self.media = parse_file_input(media, Document, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
if caption:
self.caption = caption
self.parse_mode = parse_mode
self.caption_entities = caption_entities
media = parse_file_input(media, Document, attach=True, filename=filename)
super().__init__('document', media, caption, caption_entities, parse_mode)
self.thumb = self._parse_thumb_input(thumb)
self.disable_content_type_detection = disable_content_type_detection

View file

@ -20,15 +20,13 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram._files._basemedium import _BaseMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class PhotoSize(TelegramObject):
class PhotoSize(_BaseMedium):
"""This object represents one size of a photo or a file/sticker thumbnail.
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -58,7 +56,7 @@ class PhotoSize(TelegramObject):
"""
__slots__ = ('bot', 'width', 'file_id', 'file_size', 'height', 'file_unique_id')
__slots__ = ('width', 'height')
def __init__(
self,
@ -70,29 +68,9 @@ class PhotoSize(TelegramObject):
bot: 'Bot' = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id, file_unique_id=file_unique_id, file_size=file_size, bot=bot
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.width = int(width)
self.height = int(height)
# Optionals
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)

View file

@ -21,14 +21,14 @@
from typing import TYPE_CHECKING, Any, List, Optional, ClassVar
from telegram import PhotoSize, TelegramObject, constants
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram._files._basethumbedmedium import _BaseThumbedMedium
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class Sticker(TelegramObject):
class Sticker(_BaseThumbedMedium):
"""This object represents a sticker.
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -85,18 +85,13 @@ class Sticker(TelegramObject):
"""
__slots__ = (
'bot',
'width',
'file_id',
'emoji',
'height',
'is_animated',
'is_video',
'file_size',
'thumb',
'set_name',
'mask_position',
'height',
'file_unique_id',
'emoji',
'set_name',
'width',
)
def __init__(
@ -115,22 +110,22 @@ class Sticker(TelegramObject):
bot: 'Bot' = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
bot=bot,
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.width = int(width)
self.height = int(height)
self.is_animated = is_animated
self.is_video = is_video
# Optionals
self.thumb = thumb
# Optional
self.emoji = emoji
self.file_size = file_size
self.set_name = set_name
self.mask_position = mask_position
self.bot = bot
self._id_attrs = (self.file_unique_id,)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['Sticker']:
@ -145,22 +140,6 @@ class Sticker(TelegramObject):
return cls(bot=bot, **data)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
class StickerSet(TelegramObject):
"""This object represents a sticker set.
@ -200,13 +179,13 @@ class StickerSet(TelegramObject):
"""
__slots__ = (
'contains_masks',
'is_animated',
'is_video',
'contains_masks',
'name',
'stickers',
'thumb',
'title',
'stickers',
'name',
)
def __init__(
@ -226,7 +205,7 @@ class StickerSet(TelegramObject):
self.is_video = is_video
self.contains_masks = contains_masks
self.stickers = stickers
# Optionals
# Optional
self.thumb = thumb
self._id_attrs = (self.name,)

View file

@ -61,13 +61,13 @@ class Venue(TelegramObject):
"""
__slots__ = (
'google_place_type',
'location',
'title',
'address',
'foursquare_type',
'location',
'foursquare_id',
'foursquare_type',
'google_place_id',
'google_place_type',
'title',
)
def __init__(

View file

@ -18,17 +18,16 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Video."""
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any
from telegram import PhotoSize, TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram import PhotoSize
from telegram._files._basethumbedmedium import _BaseThumbedMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class Video(TelegramObject):
class Video(_BaseThumbedMedium):
"""This object represents a video file.
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -66,18 +65,7 @@ class Video(TelegramObject):
"""
__slots__ = (
'bot',
'width',
'file_id',
'file_size',
'file_name',
'thumb',
'duration',
'mime_type',
'height',
'file_unique_id',
)
__slots__ = ('duration', 'file_name', 'height', 'mime_type', 'width')
def __init__(
self,
@ -93,45 +81,17 @@ class Video(TelegramObject):
file_name: str = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
bot=bot,
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.width = int(width)
self.height = int(height)
self.duration = int(duration)
# Optionals
self.thumb = thumb
self.file_name = file_name
self.duration = duration
# Optional
self.mime_type = mime_type
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['Video']:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
return cls(bot=bot, **data)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
self.file_name = file_name

View file

@ -18,17 +18,16 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram VideoNote."""
from typing import TYPE_CHECKING, Optional, Any
from typing import TYPE_CHECKING, Any
from telegram import PhotoSize, TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram import PhotoSize
from telegram._files._basethumbedmedium import _BaseThumbedMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class VideoNote(TelegramObject):
class VideoNote(_BaseThumbedMedium):
"""This object represents a video message (available in Telegram apps as of v.4.0).
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -61,15 +60,7 @@ class VideoNote(TelegramObject):
"""
__slots__ = (
'bot',
'length',
'file_id',
'file_size',
'thumb',
'duration',
'file_unique_id',
)
__slots__ = ('duration', 'length')
def __init__(
self,
@ -82,42 +73,13 @@ class VideoNote(TelegramObject):
bot: 'Bot' = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
thumb=thumb,
bot=bot,
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.length = int(length)
self.duration = int(duration)
# Optionals
self.thumb = thumb
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> Optional['VideoNote']:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
return cls(bot=bot, **data)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
self.duration = duration

View file

@ -20,15 +20,13 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput
from telegram._files._basemedium import _BaseMedium
if TYPE_CHECKING:
from telegram import Bot, File
from telegram import Bot
class Voice(TelegramObject):
class Voice(_BaseMedium):
"""This object represents a voice note.
Objects of this class are comparable in terms of equality. Two objects of this class are
@ -58,14 +56,7 @@ class Voice(TelegramObject):
"""
__slots__ = (
'bot',
'file_id',
'file_size',
'duration',
'mime_type',
'file_unique_id',
)
__slots__ = ('duration', 'mime_type')
def __init__(
self,
@ -77,29 +68,13 @@ class Voice(TelegramObject):
bot: 'Bot' = None,
**_kwargs: Any,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
bot=bot,
)
# Required
self.file_id = str(file_id)
self.file_unique_id = str(file_unique_id)
self.duration = int(duration)
# Optionals
# Optional
self.mime_type = mime_type
self.file_size = file_size
self.bot = bot
self._id_attrs = (self.file_unique_id,)
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`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)

View file

@ -159,10 +159,8 @@ class ExtBot(Bot):
)
# 3)
elif isinstance(val, InputMedia) and val.parse_mode is DEFAULT_NONE: # type: ignore
val.parse_mode = ( # type: ignore[attr-defined]
self.defaults.parse_mode if self.defaults else None
)
elif isinstance(val, InputMedia) and val.parse_mode is DEFAULT_NONE:
val.parse_mode = self.defaults.parse_mode if self.defaults else None
elif key == 'media' and isinstance(val, list):
for media in val:
if media.parse_mode is DEFAULT_NONE:

View file

@ -164,6 +164,8 @@ def check_object(h4):
ignored |= {'credentials'}
elif name == 'PassportElementError':
ignored |= {'message', 'type', 'source'}
elif name == 'InputMedia':
ignored |= {'caption', 'caption_entities', 'media', 'media_type', 'parse_mode'}
elif name.startswith('InputMedia'):
ignored |= {'filename'} # Convenience parameter