From 1d4464ddbd12f485c0b4b789a70d2c9a8cf8b163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20H=C3=B6ke?= Date: Thu, 9 Mar 2017 23:16:58 +0100 Subject: [PATCH 1/9] :heavy_plus_sign: add git submodule to vendor urllib3 #533 --- .gitmodules | 4 ++++ telegram/vendor/urllib3 | 1 + 2 files changed, 5 insertions(+) create mode 100644 .gitmodules create mode 160000 telegram/vendor/urllib3 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..8ee231a1c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "telegram/vendor/urllib3"] + path = telegram/vendor/urllib3 + url = https://github.com/python-telegram-bot/urllib3.git + branch = ptb diff --git a/telegram/vendor/urllib3 b/telegram/vendor/urllib3 new file mode 160000 index 000000000..4b076eedf --- /dev/null +++ b/telegram/vendor/urllib3 @@ -0,0 +1 @@ +Subproject commit 4b076eedffc1afabf0215ced3820603de73d1ce7 From 2a1d40bd28bfa747faa2c5f09ad609766e9ac39e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannes=20H=C3=B6ke?= Date: Thu, 9 Mar 2017 23:29:15 +0100 Subject: [PATCH 2/9] :construction: manipulate sys.path to prefer vendor urllib3 #533 --- telegram/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telegram/__init__.py b/telegram/__init__.py index 14946218f..13060b61d 100644 --- a/telegram/__init__.py +++ b/telegram/__init__.py @@ -19,6 +19,10 @@ """A library that provides a Python interface to the Telegram Bot API""" from sys import version_info +import sys +import os + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'vendor', 'urllib3')) from .base import TelegramObject from .user import User From 2b930c221dcb2b593f75ec25bb4e4289486bd41b Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 11 Mar 2017 16:23:43 +0200 Subject: [PATCH 3/9] Sane default for sending files timeout --- telegram/bot.py | 142 +++++++++++++++++++++++++------------- telegram/utils/request.py | 2 +- 2 files changed, 94 insertions(+), 50 deletions(-) diff --git a/telegram/bot.py b/telegram/bot.py index 031e121a5..283f10478 100644 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -129,31 +129,33 @@ class Bot(TelegramObject): return decorator + def _message_wrapper(self, url, data, *args, **kwargs): + if kwargs.get('reply_to_message_id'): + data['reply_to_message_id'] = kwargs.get('reply_to_message_id') + + if kwargs.get('disable_notification'): + data['disable_notification'] = kwargs.get('disable_notification') + + if kwargs.get('reply_markup'): + reply_markup = kwargs.get('reply_markup') + if isinstance(reply_markup, ReplyMarkup): + data['reply_markup'] = reply_markup.to_json() + else: + data['reply_markup'] = reply_markup + + result = self._request.post(url, data, timeout=kwargs.get('timeout')) + + if result is True: + return result + + return Message.de_json(result, self) + def message(func): @functools.wraps(func) def decorator(self, *args, **kwargs): url, data = func(self, *args, **kwargs) - - if kwargs.get('reply_to_message_id'): - data['reply_to_message_id'] = kwargs.get('reply_to_message_id') - - if kwargs.get('disable_notification'): - data['disable_notification'] = kwargs.get('disable_notification') - - if kwargs.get('reply_markup'): - reply_markup = kwargs.get('reply_markup') - if isinstance(reply_markup, ReplyMarkup): - data['reply_markup'] = reply_markup.to_json() - else: - data['reply_markup'] = reply_markup - - result = self._request.post(url, data, timeout=kwargs.get('timeout')) - - if result is True: - return result - - return Message.de_json(result, self) + return Bot._message_wrapper(self, url, data, *args, **kwargs) return decorator @@ -283,7 +285,6 @@ class Bot(TelegramObject): return url, data @log - @message def sendPhoto(self, chat_id, photo, @@ -291,7 +292,7 @@ class Bot(TelegramObject): disable_notification=False, reply_to_message_id=None, reply_markup=None, - timeout=None, + timeout=20., **kwargs): """Use this method to send photos. @@ -308,9 +309,7 @@ class Bot(TelegramObject): reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. - timeout (Optional[int|float]): If this value is specified, use it as the read timeout - from the server (instead of the one specified during creation of the connection - pool). + timeout (Optional[int|float]): Send file timeout (default: 20 seconds). **kwargs (dict): Arbitrary keyword arguments. Returns: @@ -327,10 +326,19 @@ class Bot(TelegramObject): if caption: data['caption'] = caption - return url, data + return self._message_wrapper( + url, + data, + chat_id=chat_id, + photo=photo, + caption=caption, + disable_notification=disable_notification, + reply_to_message_id=reply_to_message_id, + reply_markup=reply_markup, + timeout=timeout, + **kwargs) @log - @message def sendAudio(self, chat_id, audio, @@ -341,7 +349,7 @@ class Bot(TelegramObject): disable_notification=False, reply_to_message_id=None, reply_markup=None, - timeout=None, + timeout=20., **kwargs): """Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in an .mp3 format. @@ -370,9 +378,7 @@ class Bot(TelegramObject): reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. - timeout (Optional[int|float]): If this value is specified, use it as the read timeout - from the server (instead of the one specified during creation of the connection - pool). + timeout (Optional[int|float]): Send file timeout (default: 20 seconds). **kwargs (dict): Arbitrary keyword arguments. Returns: @@ -395,10 +401,22 @@ class Bot(TelegramObject): if caption: data['caption'] = caption - return url, data + return self._message_wrapper( + url, + data, + chat_id=chat_id, + audio=audio, + duration=duration, + performer=performer, + title=title, + caption=caption, + disable_notification=disable_notification, + reply_to_message_id=reply_to_message_id, + reply_markup=reply_markup, + timeout=20., + **kwargs) @log - @message def sendDocument(self, chat_id, document, @@ -407,7 +425,7 @@ class Bot(TelegramObject): disable_notification=False, reply_to_message_id=None, reply_markup=None, - timeout=None, + timeout=20., **kwargs): """Use this method to send general files. @@ -426,9 +444,7 @@ class Bot(TelegramObject): reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. - timeout (Optional[int|float]): If this value is specified, use it as the read timeout - from the server (instead of the one specified during creation of the connection - pool). + timeout (Optional[int|float]): Send file timeout (default: 20 seconds). **kwargs (dict): Arbitrary keyword arguments. Returns: @@ -447,6 +463,18 @@ class Bot(TelegramObject): if caption: data['caption'] = caption + self._message_wrapper( + url, + data, + chat_id=chat_id, + document=document, + filename=filename, + caption=caption, + disable_notification=disable_notification, + reply_to_message_id=reply_to_message_id, + reply_markup=reply_markup, + timeout=timeout, + **kwargs) return url, data @log @@ -492,7 +520,6 @@ class Bot(TelegramObject): return url, data @log - @message def sendVideo(self, chat_id, video, @@ -501,7 +528,7 @@ class Bot(TelegramObject): disable_notification=False, reply_to_message_id=None, reply_markup=None, - timeout=None, + timeout=20., **kwargs): """Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as telegram.Document). @@ -521,9 +548,7 @@ class Bot(TelegramObject): reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. - timeout (Optional[int|float]): If this value is specified, use it as the read timeout - from the server (instead of the one specified during creation of the connection - pool). + timeout (Optional[int|float]): Send file timeout (default: 20 seconds). Returns: :class:`telegram.Message`: On success, instance representing the message posted. @@ -541,10 +566,20 @@ class Bot(TelegramObject): if caption: data['caption'] = caption - return url, data + return self._message_wrapper( + url, + data, + chat_id=chat_id, + video=video, + duration=duration, + caption=caption, + disable_notification=disable_notification, + reply_to_message_id=reply_to_message_id, + reply_markup=reply_markup, + timeout=timeout, + **kwargs) @log - @message def sendVoice(self, chat_id, voice, @@ -553,7 +588,7 @@ class Bot(TelegramObject): disable_notification=False, reply_to_message_id=None, reply_markup=None, - timeout=None, + timeout=20., **kwargs): """Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .ogg file encoded with @@ -575,9 +610,7 @@ class Bot(TelegramObject): reply_markup (Optional[:class:`telegram.ReplyMarkup`]): Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. - timeout (Optional[int|float]): If this value is specified, use it as the read timeout - from the server (instead of the one specified during creation of the connection - pool). + timeout (Optional[int|float]): Send file timeout (default: 20 seconds). **kwargs (dict): Arbitrary keyword arguments. Returns: @@ -596,7 +629,18 @@ class Bot(TelegramObject): if caption: data['caption'] = caption - return url, data + return self._message_wrapper( + url, + data, + chat_id=chat_id, + voice=voice, + duration=duration, + caption=caption, + disable_notification=disable_notification, + reply_to_message_id=reply_to_message_id, + reply_markup=reply_markup, + timeout=timeout, + **kwargs) @log @message diff --git a/telegram/utils/request.py b/telegram/utils/request.py index 9f9462b48..947309afb 100644 --- a/telegram/utils/request.py +++ b/telegram/utils/request.py @@ -81,7 +81,7 @@ class Request(object): (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), ], timeout=urllib3.Timeout( - connect=self._connect_timeout, read=read_timeout),) + connect=self._connect_timeout, read=read_timeout, total=None)) # Set a proxy according to the following order: # * proxy defined in proxy_url (+ urllib3_proxy_kwargs) From d239f4ee62b3736b4542da56caf76d33a7478fdc Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 11 Mar 2017 16:51:20 +0200 Subject: [PATCH 4/9] setup.py: vendor the urllib3 package --- setup.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ff52932a0..44c6440ab 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,13 @@ def requirements(): return requirements_list +packages = find_packages(exclude=['tests*']) +packages.extend(['telegram.vendor.urllib3.urllib3', + 'telegram.vendor.urllib3.urllib3.packages', 'telegram.vendor.urllib3.urllib3.packages.ssl_match_hostname', + 'telegram.vendor.urllib3.urllib3.packages.backports', 'telegram.vendor.urllib3.urllib3.contrib', + 'telegram.vendor.urllib3.urllib3.util', + ]) + with codecs.open('README.rst', 'r', 'utf-8') as fd: fn = os.path.join('telegram', 'version.py') with open(fn) as fh: @@ -32,7 +39,7 @@ with codecs.open('README.rst', 'r', 'utf-8') as fd: keywords='python telegram bot api wrapper', description="We have made you a wrapper you can't refuse", long_description=fd.read(), - packages=find_packages(exclude=['tests*']), + packages=packages, install_requires=requirements(), extras_require={ 'json': 'ujson', From bfb99a688af2ef259994a7b443d61100ed3552ca Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 11 Mar 2017 16:58:23 +0200 Subject: [PATCH 5/9] AUTHORS.rst: Add self to maintainers and add license info about urllib3 --- AUTHORS.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 970ea5fce..627d3135e 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -3,7 +3,12 @@ Credits ``python-telegram-bot`` was originally created by `Leandro Toledo `_ and is now maintained by -`Jannes Höke `_ (`@jh0ker `_ on Telegram). +`Jannes Höke `_ (`@jh0ker `_ on Telegram) and +`Noam Meltzer `_. + +We're vendoring urllib3 as part of ``python-telegram-bot`` which is distributed under the MIT +license. For more info, full credits & license terms, the sources can be found here: +`https://github.com/python-telegram-bot/urllib3`. Contributors ------------ From 8c2ee0b4390a85b73a1d17f9fbaa4e45375e21c2 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 11 Mar 2017 17:14:15 +0200 Subject: [PATCH 6/9] Remove urllib3 from requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d0e4645c6..14d335012 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ future>=0.15.2 -urllib3>=1.10 certifi From bef6651da044b0ed2257e641590d15a4b83e6e04 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 11 Mar 2017 23:32:20 +0200 Subject: [PATCH 7/9] travis: when running nosetests run only the telegram tests (not urllib3) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index aa23e7287..ff74c09cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ install: - pip install -r requirements-dev.txt - if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then pip install ujson; fi script: - - nosetests -v --with-flaky --no-flaky-report --with-coverage --cover-package=telegram/ + - nosetests -v --with-flaky --no-flaky-report --with-coverage --cover-package=telegram/ tests - if [[ $TRAVIS_PYTHON_VERSION == 3.5 ]]; then pre-commit run --all-files; fi after_success: coveralls From 4c8d1c9a5e4f3c17c425755b8fb130243bc40927 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 11 Mar 2017 23:55:26 +0200 Subject: [PATCH 8/9] Fix Bot.sendDocument --- telegram/bot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telegram/bot.py b/telegram/bot.py index 283f10478..6b6d336c5 100644 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -463,7 +463,7 @@ class Bot(TelegramObject): if caption: data['caption'] = caption - self._message_wrapper( + return self._message_wrapper( url, data, chat_id=chat_id, @@ -475,7 +475,6 @@ class Bot(TelegramObject): reply_markup=reply_markup, timeout=timeout, **kwargs) - return url, data @log @message From 34059c951daddd5337fb480abb6ab857a662d996 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Sat, 29 Apr 2017 15:17:41 +0300 Subject: [PATCH 9/9] Don't run coveralls on the vendor subdir --- .coveragerc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index 72328e938..9c6d39cbb 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,8 @@ [run] source = telegram +omit = telegram/vendor/* [report] -omit = tests/ +omit = + tests/ + telegram/vendor/*