From a86fc6c2ac1d984f070ac0dbfe12741b96ff373d Mon Sep 17 00:00:00 2001 From: Leandro Toledo Date: Fri, 28 Aug 2015 17:45:44 -0300 Subject: [PATCH] Improving the design of existing Telegram classes --- Makefile | 15 ++- ...requirements.txt => requirements-docs.txt} | 0 telegram/audio.py | 35 +------ telegram/base.py | 14 ++- telegram/contact.py | 29 +----- telegram/document.py | 33 +------ telegram/forcereply.py | 26 +---- telegram/groupchat.py | 21 +--- telegram/location.py | 21 +--- telegram/message.py | 96 +++++-------------- telegram/photosize.py | 34 +++---- telegram/replykeyboardhide.py | 25 +---- telegram/replykeyboardmarkup.py | 31 +----- telegram/sticker.py | 31 +----- telegram/update.py | 23 +---- telegram/user.py | 29 +----- telegram/userprofilephotos.py | 14 +-- telegram/video.py | 36 +------ telegram/voice.py | 30 +----- tests/test_bot.py | 2 +- 20 files changed, 84 insertions(+), 461 deletions(-) rename docs/{docs-requirements.txt => requirements-docs.txt} (100%) diff --git a/Makefile b/Makefile index 6ebba9d0b..79d2c0ff7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: clean test lint help +.PHONY: clean pep8 lint test clean: rm -fr build @@ -7,13 +7,18 @@ clean: find . -name '*.pyo' -exec rm -f {} \; find . -name '*~' -exec rm -f {} \; +pep8: + flake8 telegram + lint: - flake8 --doctests --max-complexity 10 telegram + pylint -E telegram test: @- $(foreach TEST, $(wildcard tests/test_*.py), python $(TEST)) help: - @echo " clean remove unwanted stuff" - @echo " lint check style with flake8" - @echo " test run tests" + @echo "Available targets:" + @echo "- clean Clean up the source directory" + @echo "- pep8 Check style with flake8" + @echo "- lint Check style with pylint" + @echo "- test Run tests" diff --git a/docs/docs-requirements.txt b/docs/requirements-docs.txt similarity index 100% rename from docs/docs-requirements.txt rename to docs/requirements-docs.txt diff --git a/telegram/audio.py b/telegram/audio.py index 50a3bb753..ff54b339d 100644 --- a/telegram/audio.py +++ b/telegram/audio.py @@ -69,37 +69,4 @@ class Audio(TelegramObject): if not data: return None - audio = dict() - - # Required - audio['file_id'] = data['file_id'] - audio['duration'] = data['duration'] - # Optionals - audio['performer'] = data.get('performer') - audio['title'] = data.get('title') - audio['mime_type'] = data.get('mime_type') - audio['file_size'] = data.get('file_size', 0) - - return Audio(**audio) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['file_id'] = self.file_id - data['duration'] = self.duration - # Optionals - if self.performer: - data['performer'] = self.performer - if self.title: - data['title'] = self.title - if self.mime_type: - data['mime_type'] = self.mime_type - if self.file_size: - data['file_size'] = self.file_size - - return data + return Audio(**data) diff --git a/telegram/base.py b/telegram/base.py index 8158abfbd..bcbc04315 100644 --- a/telegram/base.py +++ b/telegram/base.py @@ -19,7 +19,7 @@ """Base class for Telegram Objects""" import json -from abc import ABCMeta, abstractmethod +from abc import ABCMeta class TelegramObject(object): @@ -51,10 +51,18 @@ class TelegramObject(object): """ return json.dumps(self.to_dict()) - @abstractmethod def to_dict(self): """ Returns: dict: """ - return None + data = dict() + + for key, value in self.__dict__.iteritems(): + if value: + if hasattr(value, 'to_dict'): + data[key] = value.to_dict() + else: + data[key] = value + + return data diff --git a/telegram/contact.py b/telegram/contact.py index 262b4bc9d..e26d755c3 100644 --- a/telegram/contact.py +++ b/telegram/contact.py @@ -63,31 +63,4 @@ class Contact(TelegramObject): if not data: return None - contact = dict() - - # Required - contact['phone_number'] = data['phone_number'] - contact['first_name'] = data['first_name'] - # Optionals - contact['last_name'] = data.get('last_name') - contact['user_id'] = data.get('user_id', 0) - - return Contact(**contact) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['phone_number'] = self.phone_number - data['first_name'] = self.first_name - # Optionals - if self.last_name: - data['last_name'] = self.last_name - if self.user_id: - data['user_id'] = self.user_id - - return data + return Contact(**data) diff --git a/telegram/document.py b/telegram/document.py index e9f7a4e7a..1fb21a92c 100644 --- a/telegram/document.py +++ b/telegram/document.py @@ -65,35 +65,4 @@ class Document(TelegramObject): if not data: return None - document = dict() - - # Required - document['file_id'] = data['file_id'] - # Optionals - document['thumb'] = PhotoSize.de_json(data.get('thumb')) - document['file_name'] = data.get('file_name') - document['mime_type'] = data.get('mime_type') - document['file_size'] = data.get('file_size', 0) - - return Document(**document) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['file_id'] = self.file_id - # Optionals - if self.thumb: - data['thumb'] = self.thumb.to_dict() - if self.file_name: - data['file_name'] = self.file_name - if self.mime_type: - data['mime_type'] = self.mime_type - if self.file_size: - data['file_size'] = self.file_size - - return data + return Document(**data) diff --git a/telegram/forcereply.py b/telegram/forcereply.py index 7e8893441..b28e8f58c 100644 --- a/telegram/forcereply.py +++ b/telegram/forcereply.py @@ -53,26 +53,8 @@ class ForceReply(ReplyMarkup): Returns: telegram.ForceReply: """ - force_reply = dict() + if not data: + return None - # Required - force_reply['force_reply'] = data['force_reply'] - # Optionals - force_reply['selective'] = data.get('selective', False) - - return ForceReply(**force_reply) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['force_reply'] = self.force_reply - # Optionals - if self.selective: - data['selective'] = self.selective - - return data + return ForceReply(**data) + diff --git a/telegram/groupchat.py b/telegram/groupchat.py index f3190b7db..1b3fac8df 100644 --- a/telegram/groupchat.py +++ b/telegram/groupchat.py @@ -53,23 +53,4 @@ class GroupChat(TelegramObject): if not data: return None - groupchat = dict() - - # Required - groupchat['id'] = data['id'] - groupchat['title'] = data['title'] - - return GroupChat(**groupchat) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['id'] = self.id - data['title'] = self.title - - return data + return GroupChat(**data) diff --git a/telegram/location.py b/telegram/location.py index b5148b7ea..66c28fc59 100644 --- a/telegram/location.py +++ b/telegram/location.py @@ -52,23 +52,4 @@ class Location(TelegramObject): if not data: return None - location = dict() - - # Required - location['longitude'] = data['longitude'] - location['latitude'] = data['latitude'] - - return Location(**location) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['longitude'] = self.longitude - data['latitude'] = self.latitude - - return data + return Location(**data) diff --git a/telegram/message.py b/telegram/message.py index 7c606d4fc..1caf61dc7 100644 --- a/telegram/message.py +++ b/telegram/message.py @@ -134,110 +134,60 @@ class Message(TelegramObject): if not data: return None - message = dict() - - # Required - message['message_id'] = data['message_id'] - message['from_user'] = User.de_json(data['from']) - message['date'] = datetime.fromtimestamp(data['date']) - # Optionals + data['from_user'] = User.de_json(data['from']) + data['date'] = datetime.fromtimestamp(data['date']) if 'first_name' in data.get('chat', ''): - message['chat'] = User.de_json(data.get('chat')) + data['chat'] = User.de_json(data.get('chat')) elif 'title' in data.get('chat', ''): - message['chat'] = GroupChat.de_json(data.get('chat')) - message['forward_from'] = \ + data['chat'] = GroupChat.de_json(data.get('chat')) + data['forward_from'] = \ User.de_json(data.get('forward_from')) - message['forward_date'] = \ + data['forward_date'] = \ Message._fromtimestamp(data.get('forward_date')) - message['reply_to_message'] = \ + data['reply_to_message'] = \ Message.de_json(data.get('reply_to_message')) - message['text'] = \ - data.get('text') - message['audio'] = \ + data['audio'] = \ Audio.de_json(data.get('audio')) - message['document'] = \ + data['document'] = \ Document.de_json(data.get('document')) - message['photo'] = \ - [PhotoSize.de_json(x) for x in data.get('photo', [])] - message['sticker'] = \ + data['photo'] = \ + PhotoSize.de_list(data.get('photo')) + data['sticker'] = \ Sticker.de_json(data.get('sticker')) - message['video'] = \ + data['video'] = \ Video.de_json(data.get('video')) - message['voice'] = \ + data['voice'] = \ Voice.de_json(data.get('voice')) - message['caption'] = \ - data.get('caption') - message['contact'] = \ + data['contact'] = \ Contact.de_json(data.get('contact')) - message['location'] = \ + data['location'] = \ Location.de_json(data.get('location')) - message['new_chat_participant'] = \ + data['new_chat_participant'] = \ User.de_json(data.get('new_chat_participant')) - message['left_chat_participant'] = \ + data['left_chat_participant'] = \ User.de_json(data.get('left_chat_participant')) - message['new_chat_title'] = \ - data.get('new_chat_title') - message['new_chat_photo'] = \ - [PhotoSize.de_json(x) for x in data.get('new_chat_photo', [])] - message['delete_chat_photo'] = \ - data.get('delete_chat_photo') - message['group_chat_created'] = \ - data.get('group_chat_created') + data['new_chat_photo'] = \ + PhotoSize.de_list(data.get('new_chat_photo')) - return Message(**message) + return Message(**data) def to_dict(self): """ Returns: dict: """ - data = dict() + data = super(Message, self).to_dict() # Required - data['message_id'] = self.message_id - data['from'] = self.from_user.to_dict() + data['from'] = data.pop('from_user') data['date'] = self._totimestamp(self.date) - data['chat'] = self.chat.to_dict() # Optionals - if self.forward_from: - data['forward_from'] = self.forward_from.to_dict() if self.forward_date: data['forward_date'] = self._totimestamp(self.forward_date) - if self.reply_to_message: - data['reply_to_message'] = self.reply_to_message.to_dict() - if self.text: - data['text'] = self.text - if self.audio: - data['audio'] = self.audio.to_dict() - if self.document: - data['document'] = self.document.to_dict() if self.photo: data['photo'] = [p.to_dict() for p in self.photo] - if self.sticker: - data['sticker'] = self.sticker.to_dict() - if self.video: - data['video'] = self.video.to_dict() - if self.voice: - data['voice'] = self.voice.to_dict() - if self.caption: - data['caption'] = self.caption - if self.contact: - data['contact'] = self.contact.to_dict() - if self.location: - data['location'] = self.location.to_dict() - if self.new_chat_participant: - data['new_chat_participant'] = self.new_chat_participant.to_dict() - if self.left_chat_participant: - data['left_chat_participant'] = \ - self.left_chat_participant.to_dict() - if self.new_chat_title: - data['new_chat_title'] = self.new_chat_title if self.new_chat_photo: data['new_chat_photo'] = [p.to_dict() for p in self.new_chat_photo] - if self.delete_chat_photo: - data['delete_chat_photo'] = self.delete_chat_photo - if self.group_chat_created: - data['group_chat_created'] = self.group_chat_created return data diff --git a/telegram/photosize.py b/telegram/photosize.py index c528e7ce9..adc47649a 100644 --- a/telegram/photosize.py +++ b/telegram/photosize.py @@ -64,30 +64,22 @@ class PhotoSize(TelegramObject): if not data: return None - photosize = dict() + return PhotoSize(**data) - # Required - photosize['file_id'] = data['file_id'] - photosize['width'] = data['width'] - photosize['height'] = data['height'] - # Optionals - photosize['file_size'] = data.get('file_size', 0) - - return PhotoSize(**photosize) - - def to_dict(self): + @staticmethod + def de_list(data): """ + Args: + data (list): + Returns: - dict: + List: """ - data = dict() + if not data: + return [] - # Required - data['file_id'] = self.file_id - data['width'] = self.width - data['height'] = self.height - # Optionals - if self.file_size: - data['file_size'] = self.file_size + photos = list() + for photo in data: + photos.append(PhotoSize.de_json(photo)) - return data + return photos diff --git a/telegram/replykeyboardhide.py b/telegram/replykeyboardhide.py index 7e0dd364e..f2cb80bb7 100644 --- a/telegram/replykeyboardhide.py +++ b/telegram/replykeyboardhide.py @@ -54,26 +54,7 @@ class ReplyKeyboardHide(ReplyMarkup): Returns: telegram.ReplyKeyboardHide: """ - rkh = dict() + if not data: + return None - # Required - rkh['hide_keyboard'] = data['hide_keyboard'] - # Optionals - rkh['selective'] = data.get('selective', False) - - return ReplyKeyboardHide(**rkh) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['hide_keyboard'] = self.hide_keyboard - # Optionals - if self.selective: - data['selective'] = self.selective - - return data + return ReplyKeyboardHide(**data) diff --git a/telegram/replykeyboardmarkup.py b/telegram/replykeyboardmarkup.py index dfd9aa2c8..39912ea39 100644 --- a/telegram/replykeyboardmarkup.py +++ b/telegram/replykeyboardmarkup.py @@ -60,32 +60,7 @@ class ReplyKeyboardMarkup(ReplyMarkup): Returns: telegram.ReplyKeyboardMarkup: """ - rkm = dict() + if not data: + return None - # Required - rkm['keyboard'] = data['keyboard'] - # Optionals - rkm['resize_keyboard'] = data.get('resize_keyboard', False) - rkm['one_time_keyboard'] = data.get('one_time_keyboard', False) - rkm['selective'] = data.get('selective', False) - - return ReplyKeyboardMarkup(**rkm) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['keyboard'] = self.keyboard - # Optionals - if self.resize_keyboard: - data['resize_keyboard'] = self.resize_keyboard - if self.one_time_keyboard: - data['one_time_keyboard'] = self.one_time_keyboard - if self.selective: - data['selective'] = self.selective - - return data + return ReplyKeyboardMarkup(**data) diff --git a/telegram/sticker.py b/telegram/sticker.py index cf7e9c7a8..c663a3fed 100644 --- a/telegram/sticker.py +++ b/telegram/sticker.py @@ -67,33 +67,4 @@ class Sticker(TelegramObject): if not data: return None - sticker = dict() - - # Required - sticker['file_id'] = data['file_id'] - sticker['width'] = data['width'] - sticker['height'] = data['height'] - # Optionals - sticker['thumb'] = PhotoSize.de_json(data['thumb']) - sticker['file_size'] = data.get('file_size', 0) - - return Sticker(**sticker) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['file_id'] = self.file_id - data['width'] = self.width - data['height'] = self.height - # Optionals - if self.thumb: - data['thumb'] = self.thumb.to_dict() - if self.file_size: - data['file_size'] = self.file_size - - return data + return Sticker(**data) diff --git a/telegram/update.py b/telegram/update.py index 9d2a9dfa5..83e068593 100644 --- a/telegram/update.py +++ b/telegram/update.py @@ -52,24 +52,9 @@ class Update(TelegramObject): Returns: telegram.Update: """ - update = dict() + if not data: + return None - update['update_id'] = data['update_id'] - update['message'] = Message.de_json(data['message']) + data['message'] = Message.de_json(data['message']) - return Update(**update) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['update_id'] = self.update_id - # Optionals - if self.message: - data['message'] = self.message.to_dict() - - return data + return Update(**data) diff --git a/telegram/user.py b/telegram/user.py index 2f36c0f14..1cdbe8e86 100644 --- a/telegram/user.py +++ b/telegram/user.py @@ -73,31 +73,4 @@ class User(TelegramObject): if not data: return None - user = dict() - - # Required - user['id'] = data['id'] - user['first_name'] = data['first_name'] - # Optionals - user['last_name'] = data.get('last_name') - user['username'] = data.get('username') - - return User(**user) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['id'] = self.id - data['first_name'] = self.first_name - # Optionals - if self.last_name: - data['last_name'] = self.last_name - if self.username: - data['username'] = self.username - - return data + return User(**data) diff --git a/telegram/userprofilephotos.py b/telegram/userprofilephotos.py index 9c9871cd1..bce623b3b 100644 --- a/telegram/userprofilephotos.py +++ b/telegram/userprofilephotos.py @@ -53,25 +53,17 @@ class UserProfilePhotos(TelegramObject): if not data: return None - upf = dict() + data['photos'] = [PhotoSize.de_list(photo) for photo in data['photos']] - # Required - upf['total_count'] = data['total_count'] - upf['photos'] = [] - for photo in data['photos']: - upf['photos'].append([PhotoSize.de_json(x) for x in photo]) - - return UserProfilePhotos(**upf) + return UserProfilePhotos(**data) def to_dict(self): """ Returns: dict: """ - data = dict() + data = super(UserProfilePhotos, self).to_dict() - # Required - data['total_count'] = self.total_count data['photos'] = [] for photo in self.photos: data['photos'].append([x.to_dict() for x in photo]) diff --git a/telegram/video.py b/telegram/video.py index ca5caf29e..b9414835b 100644 --- a/telegram/video.py +++ b/telegram/video.py @@ -74,38 +74,4 @@ class Video(TelegramObject): if not data: return None - video = dict() - - # Required - video['file_id'] = data['file_id'] - video['width'] = data['width'] - video['height'] = data['height'] - video['duration'] = data['duration'] - # Optionals - video['thumb'] = PhotoSize.de_json(data.get('thumb')) - video['mime_type'] = data.get('mime_type') - video['file_size'] = data.get('file_size', 0) - - return Video(**video) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['file_id'] = self.file_id - data['width'] = self.width - data['height'] = self.height - data['duration'] = self.duration - # Optionals - if self.thumb: - data['thumb'] = self.thumb.to_dict() - if self.mime_type: - data['mime_type'] = self.mime_type - if self.file_size: - data['file_size'] = self.file_size - - return data + return Video(**data) diff --git a/telegram/voice.py b/telegram/voice.py index fc4baec37..96f3fa5f1 100644 --- a/telegram/voice.py +++ b/telegram/voice.py @@ -62,32 +62,4 @@ class Voice(TelegramObject): if not data: return None - voice = dict() - - # Required - voice['file_id'] = data['file_id'] - # Optionals - voice['duration'] = data.get('duration', 0) - voice['mime_type'] = data.get('mime_type') - voice['file_size'] = data.get('file_size', 0) - - return Voice(**voice) - - def to_dict(self): - """ - Returns: - dict: - """ - data = dict() - - # Required - data['file_id'] = self.file_id - # Optionals - if self.duration: - data['duration'] = self.duration - if self.mime_type: - data['mime_type'] = self.mime_type - if self.file_size: - data['file_size'] = self.file_size - - return data + return Voice(**data) diff --git a/tests/test_bot.py b/tests/test_bot.py index b5d51b7e3..707b50ca7 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -53,7 +53,7 @@ class BotTest(unittest.TestCase): self.assertTrue(self.is_json(bot.to_json())) self.assertEqual(bot.id, 120405045) self.assertEqual(bot.first_name, 'Toledo\'s Palace Bot') - self.assertEqual(bot.last_name, None) + self.assertEqual(bot.last_name, '') self.assertEqual(bot.username, 'ToledosPalaceBot') self.assertEqual(bot.name, '@ToledosPalaceBot')