mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-12-22 22:45:09 +01:00
Freeze Classes Without Arguments (#3453)
This commit is contained in:
parent
f3a9b74445
commit
7b61a30fb1
12 changed files with 118 additions and 85 deletions
|
@ -122,6 +122,11 @@ class ForumTopicClosed(TelegramObject):
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
||||||
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
self._freeze()
|
||||||
|
|
||||||
|
|
||||||
class ForumTopicReopened(TelegramObject):
|
class ForumTopicReopened(TelegramObject):
|
||||||
"""
|
"""
|
||||||
|
@ -132,3 +137,8 @@ class ForumTopicReopened(TelegramObject):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
||||||
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
self._freeze()
|
||||||
|
|
|
@ -19,9 +19,15 @@
|
||||||
"""This module contains an object that represents a Telegram CallbackGame."""
|
"""This module contains an object that represents a Telegram CallbackGame."""
|
||||||
|
|
||||||
from telegram._telegramobject import TelegramObject
|
from telegram._telegramobject import TelegramObject
|
||||||
|
from telegram._utils.types import JSONDict
|
||||||
|
|
||||||
|
|
||||||
class CallbackGame(TelegramObject):
|
class CallbackGame(TelegramObject):
|
||||||
"""A placeholder, currently holds no information. Use BotFather to set up your game."""
|
"""A placeholder, currently holds no information. Use BotFather to set up your game."""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
||||||
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
self._freeze()
|
||||||
|
|
|
@ -56,14 +56,12 @@ class InputContactMessageContent(InputMessageContent):
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
):
|
):
|
||||||
super().__init__(api_kwargs=api_kwargs)
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
with self._unfrozen():
|
||||||
|
# Required
|
||||||
|
self.phone_number = phone_number
|
||||||
|
self.first_name = first_name
|
||||||
|
# Optionals
|
||||||
|
self.last_name = last_name
|
||||||
|
self.vcard = vcard
|
||||||
|
|
||||||
# Required
|
self._id_attrs = (self.phone_number,)
|
||||||
self.phone_number = phone_number
|
|
||||||
self.first_name = first_name
|
|
||||||
# Optionals
|
|
||||||
self.last_name = last_name
|
|
||||||
self.vcard = vcard
|
|
||||||
|
|
||||||
self._id_attrs = (self.phone_number,)
|
|
||||||
|
|
||||||
self._freeze()
|
|
||||||
|
|
|
@ -200,39 +200,38 @@ class InputInvoiceMessageContent(InputMessageContent):
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
):
|
):
|
||||||
super().__init__(api_kwargs=api_kwargs)
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
# Required
|
with self._unfrozen():
|
||||||
self.title = title
|
# Required
|
||||||
self.description = description
|
self.title = title
|
||||||
self.payload = payload
|
self.description = description
|
||||||
self.provider_token = provider_token
|
self.payload = payload
|
||||||
self.currency = currency
|
self.provider_token = provider_token
|
||||||
self.prices = parse_sequence_arg(prices)
|
self.currency = currency
|
||||||
# Optionals
|
self.prices = parse_sequence_arg(prices)
|
||||||
self.max_tip_amount = max_tip_amount
|
# Optionals
|
||||||
self.suggested_tip_amounts = parse_sequence_arg(suggested_tip_amounts)
|
self.max_tip_amount = max_tip_amount
|
||||||
self.provider_data = provider_data
|
self.suggested_tip_amounts = parse_sequence_arg(suggested_tip_amounts)
|
||||||
self.photo_url = photo_url
|
self.provider_data = provider_data
|
||||||
self.photo_size = photo_size
|
self.photo_url = photo_url
|
||||||
self.photo_width = photo_width
|
self.photo_size = photo_size
|
||||||
self.photo_height = photo_height
|
self.photo_width = photo_width
|
||||||
self.need_name = need_name
|
self.photo_height = photo_height
|
||||||
self.need_phone_number = need_phone_number
|
self.need_name = need_name
|
||||||
self.need_email = need_email
|
self.need_phone_number = need_phone_number
|
||||||
self.need_shipping_address = need_shipping_address
|
self.need_email = need_email
|
||||||
self.send_phone_number_to_provider = send_phone_number_to_provider
|
self.need_shipping_address = need_shipping_address
|
||||||
self.send_email_to_provider = send_email_to_provider
|
self.send_phone_number_to_provider = send_phone_number_to_provider
|
||||||
self.is_flexible = is_flexible
|
self.send_email_to_provider = send_email_to_provider
|
||||||
|
self.is_flexible = is_flexible
|
||||||
|
|
||||||
self._id_attrs = (
|
self._id_attrs = (
|
||||||
self.title,
|
self.title,
|
||||||
self.description,
|
self.description,
|
||||||
self.payload,
|
self.payload,
|
||||||
self.provider_token,
|
self.provider_token,
|
||||||
self.currency,
|
self.currency,
|
||||||
self.prices,
|
self.prices,
|
||||||
)
|
)
|
||||||
|
|
||||||
self._freeze()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def de_json(
|
def de_json(
|
||||||
|
|
|
@ -83,21 +83,20 @@ class InputLocationMessageContent(InputMessageContent):
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
):
|
):
|
||||||
super().__init__(api_kwargs=api_kwargs)
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
# Required
|
with self._unfrozen():
|
||||||
self.latitude = latitude
|
# Required
|
||||||
self.longitude = longitude
|
self.latitude = latitude
|
||||||
|
self.longitude = longitude
|
||||||
|
|
||||||
# Optionals
|
# Optionals
|
||||||
self.live_period = live_period
|
self.live_period = live_period
|
||||||
self.horizontal_accuracy = horizontal_accuracy
|
self.horizontal_accuracy = horizontal_accuracy
|
||||||
self.heading = heading
|
self.heading = heading
|
||||||
self.proximity_alert_radius = (
|
self.proximity_alert_radius = (
|
||||||
int(proximity_alert_radius) if proximity_alert_radius else None
|
int(proximity_alert_radius) if proximity_alert_radius else None
|
||||||
)
|
)
|
||||||
|
|
||||||
self._id_attrs = (self.latitude, self.longitude)
|
self._id_attrs = (self.latitude, self.longitude)
|
||||||
|
|
||||||
self._freeze()
|
|
||||||
|
|
||||||
HORIZONTAL_ACCURACY: ClassVar[int] = constants.LocationLimit.HORIZONTAL_ACCURACY
|
HORIZONTAL_ACCURACY: ClassVar[int] = constants.LocationLimit.HORIZONTAL_ACCURACY
|
||||||
""":const:`telegram.constants.LocationLimit.HORIZONTAL_ACCURACY`
|
""":const:`telegram.constants.LocationLimit.HORIZONTAL_ACCURACY`
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
"""This module contains the classes that represent Telegram InputMessageContent."""
|
"""This module contains the classes that represent Telegram InputMessageContent."""
|
||||||
|
|
||||||
from telegram._telegramobject import TelegramObject
|
from telegram._telegramobject import TelegramObject
|
||||||
|
from telegram._utils.types import JSONDict
|
||||||
|
|
||||||
|
|
||||||
class InputMessageContent(TelegramObject):
|
class InputMessageContent(TelegramObject):
|
||||||
|
@ -32,3 +33,8 @@ class InputMessageContent(TelegramObject):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
||||||
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
self._freeze()
|
||||||
|
|
|
@ -78,13 +78,12 @@ class InputTextMessageContent(InputMessageContent):
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
):
|
):
|
||||||
super().__init__(api_kwargs=api_kwargs)
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
# Required
|
with self._unfrozen():
|
||||||
self.message_text = message_text
|
# Required
|
||||||
# Optionals
|
self.message_text = message_text
|
||||||
self.parse_mode = parse_mode
|
# Optionals
|
||||||
self.entities = parse_sequence_arg(entities)
|
self.parse_mode = parse_mode
|
||||||
self.disable_web_page_preview = disable_web_page_preview
|
self.entities = parse_sequence_arg(entities)
|
||||||
|
self.disable_web_page_preview = disable_web_page_preview
|
||||||
|
|
||||||
self._id_attrs = (self.message_text,)
|
self._id_attrs = (self.message_text,)
|
||||||
|
|
||||||
self._freeze()
|
|
||||||
|
|
|
@ -84,22 +84,20 @@ class InputVenueMessageContent(InputMessageContent):
|
||||||
api_kwargs: JSONDict = None,
|
api_kwargs: JSONDict = None,
|
||||||
):
|
):
|
||||||
super().__init__(api_kwargs=api_kwargs)
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
with self._unfrozen():
|
||||||
|
# Required
|
||||||
|
self.latitude = latitude
|
||||||
|
self.longitude = longitude
|
||||||
|
self.title = title
|
||||||
|
self.address = address
|
||||||
|
# Optionals
|
||||||
|
self.foursquare_id = foursquare_id
|
||||||
|
self.foursquare_type = foursquare_type
|
||||||
|
self.google_place_id = google_place_id
|
||||||
|
self.google_place_type = google_place_type
|
||||||
|
|
||||||
# Required
|
self._id_attrs = (
|
||||||
self.latitude = latitude
|
self.latitude,
|
||||||
self.longitude = longitude
|
self.longitude,
|
||||||
self.title = title
|
self.title,
|
||||||
self.address = address
|
)
|
||||||
# Optionals
|
|
||||||
self.foursquare_id = foursquare_id
|
|
||||||
self.foursquare_type = foursquare_type
|
|
||||||
self.google_place_id = google_place_id
|
|
||||||
self.google_place_type = google_place_type
|
|
||||||
|
|
||||||
self._id_attrs = (
|
|
||||||
self.latitude,
|
|
||||||
self.longitude,
|
|
||||||
self.title,
|
|
||||||
)
|
|
||||||
|
|
||||||
self._freeze()
|
|
||||||
|
|
|
@ -92,6 +92,10 @@ class TelegramObject:
|
||||||
__INIT_PARAMS_CHECK: Optional[Type["TelegramObject"]] = None
|
__INIT_PARAMS_CHECK: Optional[Type["TelegramObject"]] = None
|
||||||
|
|
||||||
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
||||||
|
# Setting _frozen to `False` here means that classes without arguments still need to
|
||||||
|
# implement __init__. However, with `True` would mean increased usage of
|
||||||
|
# `with self._unfrozen()` in the `__init__` of subclasses and we have fewer empty
|
||||||
|
# classes than classes with arguments.
|
||||||
self._frozen: bool = False
|
self._frozen: bool = False
|
||||||
self._id_attrs: Tuple[object, ...] = ()
|
self._id_attrs: Tuple[object, ...] = ()
|
||||||
self._bot: Optional["Bot"] = None
|
self._bot: Optional["Bot"] = None
|
||||||
|
|
|
@ -42,6 +42,11 @@ class VideoChatStarted(TelegramObject):
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __init__(self, *, api_kwargs: JSONDict = None) -> None:
|
||||||
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
|
||||||
|
self._freeze()
|
||||||
|
|
||||||
|
|
||||||
class VideoChatEnded(TelegramObject):
|
class VideoChatEnded(TelegramObject):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -185,6 +185,7 @@ class InputMessageContentDWPP(InputMessageContent):
|
||||||
api_kwargs=None,
|
api_kwargs=None,
|
||||||
):
|
):
|
||||||
super().__init__(api_kwargs=api_kwargs)
|
super().__init__(api_kwargs=api_kwargs)
|
||||||
|
self._unfreeze()
|
||||||
self.message_text = message_text
|
self.message_text = message_text
|
||||||
self.disable_web_page_preview = disable_web_page_preview
|
self.disable_web_page_preview = disable_web_page_preview
|
||||||
|
|
||||||
|
|
|
@ -428,7 +428,8 @@ class TestTelegramObject:
|
||||||
|
|
||||||
@pytest.mark.parametrize("cls", TO_SUBCLASSES, ids=[cls.__name__ for cls in TO_SUBCLASSES])
|
@pytest.mark.parametrize("cls", TO_SUBCLASSES, ids=[cls.__name__ for cls in TO_SUBCLASSES])
|
||||||
def test_subclasses_are_frozen(self, cls):
|
def test_subclasses_are_frozen(self, cls):
|
||||||
if cls.__name__.startswith("_"):
|
if cls is TelegramObject or cls.__name__.startswith("_"):
|
||||||
|
# Protected classes don't need to be frozen and neither does the base class
|
||||||
return
|
return
|
||||||
|
|
||||||
# instantiating each subclass would be tedious as some attributes require special init
|
# instantiating each subclass would be tedious as some attributes require special init
|
||||||
|
@ -437,10 +438,17 @@ class TestTelegramObject:
|
||||||
source_file = inspect.getsourcefile(cls.__init__)
|
source_file = inspect.getsourcefile(cls.__init__)
|
||||||
parents = Path(source_file).parents
|
parents = Path(source_file).parents
|
||||||
is_test_file = Path(__file__).parent.resolve() in parents
|
is_test_file = Path(__file__).parent.resolve() in parents
|
||||||
if is_test_file or source_file.endswith("telegramobject.py"):
|
|
||||||
# classes without their own `__init__` can be ignored
|
if is_test_file:
|
||||||
|
# If the class is defined in a test file, we don't want to test it.
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if source_file.endswith("telegramobject.py"):
|
||||||
|
pytest.fail(
|
||||||
|
f"{cls.__name__} does not have its own `__init__` "
|
||||||
|
"and can therefore not be frozen correctly"
|
||||||
|
)
|
||||||
|
|
||||||
source_lines, first_line = inspect.getsourcelines(cls.__init__)
|
source_lines, first_line = inspect.getsourcelines(cls.__init__)
|
||||||
|
|
||||||
# We use regex matching since a simple "if self._freeze() in source_lines[-1]" would also
|
# We use regex matching since a simple "if self._freeze() in source_lines[-1]" would also
|
||||||
|
|
Loading…
Reference in a new issue