We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
support socks5 proxy.
First of all, everthing works well. Very thanks for your working on this awesome lib.

But in China, telegram is been blocked by gov. When deploying the bot in China, it's unable to reply message to the api server, can receive message from telegram.

I tried to set up a sock5 proxy, but failed. Is there any plan for supporting the sock5 proxy?

![image](https://cloud.githubusercontent.com/assets/2503423/22633710/d62f7b6e-ec5e-11e6-870f-ace293672f04.png)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setup.py`
Content:
```
1 #!/usr/bin/env python
2 """The setup and build script for the python-telegram-bot library."""
3 
4 import codecs
5 import os
6 from setuptools import setup, find_packages
7 
8 
9 def requirements():
10     """Build the requirements list for this project"""
11     requirements_list = []
12 
13     with open('requirements.txt') as requirements:
14         for install in requirements:
15             requirements_list.append(install.strip())
16 
17     return requirements_list
18 
19 
20 with codecs.open('README.rst', 'r', 'utf-8') as fd:
21     fn = os.path.join('telegram', 'version.py')
22     with open(fn) as fh:
23         code = compile(fh.read(), fn, 'exec')
24         exec(code)
25 
26     setup(name='python-telegram-bot',
27           version=__version__,
28           author='Leandro Toledo',
29           author_email='devs@python-telegram-bot.org',
30           license='LGPLv3',
31           url='https://python-telegram-bot.org/',
32           keywords='python telegram bot api wrapper',
33           description="We have made you a wrapper you can't refuse",
34           long_description=fd.read(),
35           packages=find_packages(exclude=['tests*']),
36           install_requires=requirements(),
37           extras_require={
38               'json': 'ujson',
39           },
40           include_package_data=True,
41           classifiers=[
42               'Development Status :: 5 - Production/Stable',
43               'Intended Audience :: Developers',
44               'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
45               'Operating System :: OS Independent',
46               'Topic :: Software Development :: Libraries :: Python Modules',
47               'Topic :: Communications :: Chat',
48               'Topic :: Internet',
49               'Programming Language :: Python',
50               'Programming Language :: Python :: 2',
51               'Programming Language :: Python :: 2.7',
52               'Programming Language :: Python :: 3',
53               'Programming Language :: Python :: 3.3',
54               'Programming Language :: Python :: 3.4',
55               'Programming Language :: Python :: 3.5',
56               'Programming Language :: Python :: 3.6'
57           ],)
58
```

Path: `telegram/utils/request.py`
Content:
```
1 #!/usr/bin/env python
2 #
3 # A library that provides a Python interface to the Telegram Bot API
4 # Copyright (C) 2015-2016
5 # Leandro Toledo de Souza <devs@python-telegram-bot.org>
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Lesser Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Lesser Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser Public License
18 # along with this program.  If not, see [http://www.gnu.org/licenses/].
19 """This module contains methods to make POST and GET requests"""
20 import os
21 import socket
22 import logging
23 
24 try:
25     import ujson as json
26 except ImportError:
27     import json
28 
29 import certifi
30 import urllib3
31 from urllib3.connection import HTTPConnection
32 from urllib3.util.timeout import Timeout
33 
34 from telegram import (InputFile, TelegramError)
35 from telegram.error import (Unauthorized, NetworkError, TimedOut, BadRequest, ChatMigrated,
36                             RetryAfter, InvalidToken)
37 
38 logging.getLogger('urllib3').setLevel(logging.WARNING)
39 
40 
41 class Request(object):
42     """
43     Helper class for python-telegram-bot which provides methods to perform POST & GET towards
44     telegram servers.
45 
46     Args:
47         con_pool_size (int): Number of connections to keep in the connection pool.
48         proxy_url (str): The URL to the proxy server. For example: `http://127.0.0.1:3128`.
49         urllib3_proxy_kwargs (dict): Arbitrary arguments passed as-is to `urllib3.ProxyManager`.
50             This value will be ignored if proxy_url is not set.
51         connect_timeout (int|float): The maximum amount of time (in seconds) to wait for a
52             connection attempt to a server to succeed. None will set an infinite timeout for
53             connection attempts. (default: 5.)
54         read_timeout (int|float): The maximum amount of time (in seconds) to wait between
55             consecutive read operations for a response from the server. None will set an infinite
56             timeout. This value is usually overridden by the various ``telegram.Bot`` methods.
57             (default: 5.)
58 
59     """
60 
61     def __init__(self,
62                  con_pool_size=1,
63                  proxy_url=None,
64                  urllib3_proxy_kwargs=None,
65                  connect_timeout=5.,
66                  read_timeout=5.):
67         if urllib3_proxy_kwargs is None:
68             urllib3_proxy_kwargs = dict()
69 
70         self._connect_timeout = connect_timeout
71 
72         kwargs = dict(
73             maxsize=con_pool_size,
74             cert_reqs='CERT_REQUIRED',
75             ca_certs=certifi.where(),
76             socket_options=HTTPConnection.default_socket_options + [
77                 (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
78             ],
79             timeout=urllib3.Timeout(
80                 connect=self._connect_timeout, read=read_timeout),)
81 
82         # Set a proxy according to the following order:
83         # * proxy defined in proxy_url (+ urllib3_proxy_kwargs)
84         # * proxy set in `HTTPS_PROXY` env. var.
85         # * proxy set in `https_proxy` env. var.
86         # * None (if no proxy is configured)
87 
88         if not proxy_url:
89             proxy_url = os.environ.get('HTTPS_PROXY') or os.environ.get('https_proxy')
90 
91         if not proxy_url:
92             mgr = urllib3.PoolManager(**kwargs)
93         else:
94             kwargs.update(urllib3_proxy_kwargs)
95             mgr = urllib3.proxy_from_url(proxy_url, **kwargs)
96             if mgr.proxy.auth:
97                 # TODO: what about other auth types?
98                 auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)
99                 mgr.proxy_headers.update(auth_hdrs)
100 
101         self._con_pool = mgr
102 
103     def stop(self):
104         self._con_pool.clear()
105 
106     @staticmethod
107     def _parse(json_data):
108         """Try and parse the JSON returned from Telegram.
109 
110         Returns:
111             dict: A JSON parsed as Python dict with results - on error this dict will be empty.
112 
113         """
114         decoded_s = json_data.decode('utf-8')
115         try:
116             data = json.loads(decoded_s)
117         except ValueError:
118             raise TelegramError('Invalid server response')
119 
120         if not data.get('ok'):
121             description = data.get('description')
122             parameters = data.get('parameters')
123             if parameters:
124                 migrate_to_chat_id = parameters.get('migrate_to_chat_id')
125                 if migrate_to_chat_id:
126                     raise ChatMigrated(migrate_to_chat_id)
127                 retry_after = parameters.get('retry_after')
128                 if retry_after:
129                     raise RetryAfter(retry_after)
130             if description:
131                 return description
132 
133         return data['result']
134 
135     def _request_wrapper(self, *args, **kwargs):
136         """Wraps urllib3 request for handling known exceptions.
137 
138         Args:
139             args: unnamed arguments, passed to urllib3 request.
140             kwargs: keyword arguments, passed tp urllib3 request.
141 
142         Returns:
143             str: A non-parsed JSON text.
144 
145         Raises:
146             TelegramError
147 
148         """
149         # Make sure to hint Telegram servers that we reuse connections by sending
150         # "Connection: keep-alive" in the HTTP headers.
151         if 'headers' not in kwargs:
152             kwargs['headers'] = {}
153         kwargs['headers']['connection'] = 'keep-alive'
154 
155         try:
156             resp = self._con_pool.request(*args, **kwargs)
157         except urllib3.exceptions.TimeoutError:
158             raise TimedOut()
159         except urllib3.exceptions.HTTPError as error:
160             # HTTPError must come last as its the base urllib3 exception class
161             # TODO: do something smart here; for now just raise NetworkError
162             raise NetworkError('urllib3 HTTPError {0}'.format(error))
163 
164         if 200 <= resp.status <= 299:
165             # 200-299 range are HTTP success statuses
166             return resp.data
167 
168         try:
169             message = self._parse(resp.data)
170         except ValueError:
171             raise NetworkError('Unknown HTTPError {0}'.format(resp.status))
172 
173         if resp.status in (401, 403):
174             raise Unauthorized()
175         elif resp.status == 400:
176             raise BadRequest(repr(message))
177         elif resp.status == 404:
178             raise InvalidToken()
179         elif resp.status == 502:
180             raise NetworkError('Bad Gateway')
181         else:
182             raise NetworkError('{0} ({1})'.format(message, resp.status))
183 
184     def get(self, url, timeout=None):
185         """Request an URL.
186 
187         Args:
188             url (str): The web location we want to retrieve.
189             timeout (Optional[int|float]): If this value is specified, use it as the read timeout
190                 from the server (instead of the one specified during creation of the connection
191                 pool).
192 
193         Returns:
194           A JSON object.
195 
196         """
197         urlopen_kwargs = {}
198 
199         if timeout is not None:
200             urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)
201 
202         result = self._request_wrapper('GET', url, **urlopen_kwargs)
203         return self._parse(result)
204 
205     def post(self, url, data, timeout=None):
206         """Request an URL.
207         Args:
208             url (str): The web location we want to retrieve.
209             data (dict[str, str]): A dict of key/value pairs. Note: On py2.7 value is unicode.
210             timeout (Optional[int|float]): If this value is specified, use it as the read timeout
211                 from the server (instead of the one specified during creation of the connection
212                 pool).
213 
214         Returns:
215           A JSON object.
216 
217         """
218         urlopen_kwargs = {}
219 
220         if timeout is not None:
221             urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)
222 
223         if InputFile.is_inputfile(data):
224             data = InputFile(data)
225             result = self._request_wrapper(
226                 'POST', url, body=data.to_form(), headers=data.headers, **urlopen_kwargs)
227         else:
228             data = json.dumps(data)
229             result = self._request_wrapper(
230                 'POST',
231                 url,
232                 body=data.encode(),
233                 headers={'Content-Type': 'application/json'},
234                 **urlopen_kwargs)
235 
236         return self._parse(result)
237 
238     def retrieve(self, url, timeout=None):
239         """Retrieve the contents of a file by its URL.
240 
241         Args:
242             url (str): The web location we want to retrieve.
243             timeout (Optional[int|float]): If this value is specified, use it as the read timeout
244                 from the server (instead of the one specified during creation of the connection
245                 pool).
246 
247         """
248         urlopen_kwargs = {}
249         if timeout is not None:
250             urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)
251 
252         return self._request_wrapper('GET', url, **urlopen_kwargs)
253 
254     def download(self, url, filename, timeout=None):
255         """Download a file by its URL.
256         Args:
257             url (str): The web location we want to retrieve.
258             timeout (Optional[int|float]): If this value is specified, use it as the read timeout
259                 from the server (instead of the one specified during creation of the connection
260                 pool).
261 
262           filename:
263             The filename within the path to download the file.
264 
265         """
266         buf = self.retrieve(url, timeout=timeout)
267         with open(filename, 'wb') as fobj:
268             fobj.write(buf)
269
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -36,6 +36,7 @@
           install_requires=requirements(),
           extras_require={
               'json': 'ujson',
+              'socks': 'PySocks'
           },
           include_package_data=True,
           classifiers=[
diff --git a/telegram/utils/request.py b/telegram/utils/request.py
--- a/telegram/utils/request.py
+++ b/telegram/utils/request.py
@@ -30,6 +30,10 @@
 import urllib3
 from urllib3.connection import HTTPConnection
 from urllib3.util.timeout import Timeout
+try:
+    from urllib3.contrib.socks import SOCKSProxyManager
+except ImportError:
+    SOCKSProxyManager = None
 
 from telegram import (InputFile, TelegramError)
 from telegram.error import (Unauthorized, NetworkError, TimedOut, BadRequest, ChatMigrated,
@@ -92,11 +96,16 @@
             mgr = urllib3.PoolManager(**kwargs)
         else:
             kwargs.update(urllib3_proxy_kwargs)
-            mgr = urllib3.proxy_from_url(proxy_url, **kwargs)
-            if mgr.proxy.auth:
-                # TODO: what about other auth types?
-                auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)
-                mgr.proxy_headers.update(auth_hdrs)
+            if proxy_url.startswith('socks'):
+                if not SOCKSProxyManager:
+                    raise RuntimeError('PySocks is missing')
+                mgr = SOCKSProxyManager(proxy_url, **kwargs)
+            else:
+                mgr = urllib3.proxy_from_url(proxy_url, **kwargs)
+                if mgr.proxy.auth:
+                    # TODO: what about other auth types?
+                    auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)
+                    mgr.proxy_headers.update(auth_hdrs)
 
         self._con_pool = mgr

{"golden_diff": "diff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -36,6 +36,7 @@\n           install_requires=requirements(),\n           extras_require={\n               'json': 'ujson',\n+              'socks': 'PySocks'\n           },\n           include_package_data=True,\n           classifiers=[\ndiff --git a/telegram/utils/request.py b/telegram/utils/request.py\n--- a/telegram/utils/request.py\n+++ b/telegram/utils/request.py\n@@ -30,6 +30,10 @@\n import urllib3\n from urllib3.connection import HTTPConnection\n from urllib3.util.timeout import Timeout\n+try:\n+    from urllib3.contrib.socks import SOCKSProxyManager\n+except ImportError:\n+    SOCKSProxyManager = None\n \n from telegram import (InputFile, TelegramError)\n from telegram.error import (Unauthorized, NetworkError, TimedOut, BadRequest, ChatMigrated,\n@@ -92,11 +96,16 @@\n             mgr = urllib3.PoolManager(**kwargs)\n         else:\n             kwargs.update(urllib3_proxy_kwargs)\n-            mgr = urllib3.proxy_from_url(proxy_url, **kwargs)\n-            if mgr.proxy.auth:\n-                # TODO: what about other auth types?\n-                auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)\n-                mgr.proxy_headers.update(auth_hdrs)\n+            if proxy_url.startswith('socks'):\n+                if not SOCKSProxyManager:\n+                    raise RuntimeError('PySocks is missing')\n+                mgr = SOCKSProxyManager(proxy_url, **kwargs)\n+            else:\n+                mgr = urllib3.proxy_from_url(proxy_url, **kwargs)\n+                if mgr.proxy.auth:\n+                    # TODO: what about other auth types?\n+                    auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)\n+                    mgr.proxy_headers.update(auth_hdrs)\n \n         self._con_pool = mgr\n", "issue": "support socks5 proxy.\nFirst of all, everthing works well. Very thanks for your working on this awesome lib.\r\n\r\nBut in China, telegram is been blocked by gov. When deploying the bot in China, it's unable to reply message to the api server, can receive message from telegram.\r\n\r\nI tried to set up a sock5 proxy, but failed. Is there any plan for supporting the sock5 proxy?\r\n\r\n![image](https://cloud.githubusercontent.com/assets/2503423/22633710/d62f7b6e-ec5e-11e6-870f-ace293672f04.png)\r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n\"\"\"The setup and build script for the python-telegram-bot library.\"\"\"\n\nimport codecs\nimport os\nfrom setuptools import setup, find_packages\n\n\ndef requirements():\n    \"\"\"Build the requirements list for this project\"\"\"\n    requirements_list = []\n\n    with open('requirements.txt') as requirements:\n        for install in requirements:\n            requirements_list.append(install.strip())\n\n    return requirements_list\n\n\nwith codecs.open('README.rst', 'r', 'utf-8') as fd:\n    fn = os.path.join('telegram', 'version.py')\n    with open(fn) as fh:\n        code = compile(fh.read(), fn, 'exec')\n        exec(code)\n\n    setup(name='python-telegram-bot',\n          version=__version__,\n          author='Leandro Toledo',\n          author_email='devs@python-telegram-bot.org',\n          license='LGPLv3',\n          url='https://python-telegram-bot.org/',\n          keywords='python telegram bot api wrapper',\n          description=\"We have made you a wrapper you can't refuse\",\n          long_description=fd.read(),\n          packages=find_packages(exclude=['tests*']),\n          install_requires=requirements(),\n          extras_require={\n              'json': 'ujson',\n          },\n          include_package_data=True,\n          classifiers=[\n              'Development Status :: 5 - Production/Stable',\n              'Intended Audience :: Developers',\n              'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',\n              'Operating System :: OS Independent',\n              'Topic :: Software Development :: Libraries :: Python Modules',\n              'Topic :: Communications :: Chat',\n              'Topic :: Internet',\n              'Programming Language :: Python',\n              'Programming Language :: Python :: 2',\n              'Programming Language :: Python :: 2.7',\n              'Programming Language :: Python :: 3',\n              'Programming Language :: Python :: 3.3',\n              'Programming Language :: Python :: 3.4',\n              'Programming Language :: Python :: 3.5',\n              'Programming Language :: Python :: 3.6'\n          ],)\n", "path": "setup.py"}, {"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2016\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains methods to make POST and GET requests\"\"\"\nimport os\nimport socket\nimport logging\n\ntry:\n    import ujson as json\nexcept ImportError:\n    import json\n\nimport certifi\nimport urllib3\nfrom urllib3.connection import HTTPConnection\nfrom urllib3.util.timeout import Timeout\n\nfrom telegram import (InputFile, TelegramError)\nfrom telegram.error import (Unauthorized, NetworkError, TimedOut, BadRequest, ChatMigrated,\n                            RetryAfter, InvalidToken)\n\nlogging.getLogger('urllib3').setLevel(logging.WARNING)\n\n\nclass Request(object):\n    \"\"\"\n    Helper class for python-telegram-bot which provides methods to perform POST & GET towards\n    telegram servers.\n\n    Args:\n        con_pool_size (int): Number of connections to keep in the connection pool.\n        proxy_url (str): The URL to the proxy server. For example: `http://127.0.0.1:3128`.\n        urllib3_proxy_kwargs (dict): Arbitrary arguments passed as-is to `urllib3.ProxyManager`.\n            This value will be ignored if proxy_url is not set.\n        connect_timeout (int|float): The maximum amount of time (in seconds) to wait for a\n            connection attempt to a server to succeed. None will set an infinite timeout for\n            connection attempts. (default: 5.)\n        read_timeout (int|float): The maximum amount of time (in seconds) to wait between\n            consecutive read operations for a response from the server. None will set an infinite\n            timeout. This value is usually overridden by the various ``telegram.Bot`` methods.\n            (default: 5.)\n\n    \"\"\"\n\n    def __init__(self,\n                 con_pool_size=1,\n                 proxy_url=None,\n                 urllib3_proxy_kwargs=None,\n                 connect_timeout=5.,\n                 read_timeout=5.):\n        if urllib3_proxy_kwargs is None:\n            urllib3_proxy_kwargs = dict()\n\n        self._connect_timeout = connect_timeout\n\n        kwargs = dict(\n            maxsize=con_pool_size,\n            cert_reqs='CERT_REQUIRED',\n            ca_certs=certifi.where(),\n            socket_options=HTTPConnection.default_socket_options + [\n                (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),\n            ],\n            timeout=urllib3.Timeout(\n                connect=self._connect_timeout, read=read_timeout),)\n\n        # Set a proxy according to the following order:\n        # * proxy defined in proxy_url (+ urllib3_proxy_kwargs)\n        # * proxy set in `HTTPS_PROXY` env. var.\n        # * proxy set in `https_proxy` env. var.\n        # * None (if no proxy is configured)\n\n        if not proxy_url:\n            proxy_url = os.environ.get('HTTPS_PROXY') or os.environ.get('https_proxy')\n\n        if not proxy_url:\n            mgr = urllib3.PoolManager(**kwargs)\n        else:\n            kwargs.update(urllib3_proxy_kwargs)\n            mgr = urllib3.proxy_from_url(proxy_url, **kwargs)\n            if mgr.proxy.auth:\n                # TODO: what about other auth types?\n                auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)\n                mgr.proxy_headers.update(auth_hdrs)\n\n        self._con_pool = mgr\n\n    def stop(self):\n        self._con_pool.clear()\n\n    @staticmethod\n    def _parse(json_data):\n        \"\"\"Try and parse the JSON returned from Telegram.\n\n        Returns:\n            dict: A JSON parsed as Python dict with results - on error this dict will be empty.\n\n        \"\"\"\n        decoded_s = json_data.decode('utf-8')\n        try:\n            data = json.loads(decoded_s)\n        except ValueError:\n            raise TelegramError('Invalid server response')\n\n        if not data.get('ok'):\n            description = data.get('description')\n            parameters = data.get('parameters')\n            if parameters:\n                migrate_to_chat_id = parameters.get('migrate_to_chat_id')\n                if migrate_to_chat_id:\n                    raise ChatMigrated(migrate_to_chat_id)\n                retry_after = parameters.get('retry_after')\n                if retry_after:\n                    raise RetryAfter(retry_after)\n            if description:\n                return description\n\n        return data['result']\n\n    def _request_wrapper(self, *args, **kwargs):\n        \"\"\"Wraps urllib3 request for handling known exceptions.\n\n        Args:\n            args: unnamed arguments, passed to urllib3 request.\n            kwargs: keyword arguments, passed tp urllib3 request.\n\n        Returns:\n            str: A non-parsed JSON text.\n\n        Raises:\n            TelegramError\n\n        \"\"\"\n        # Make sure to hint Telegram servers that we reuse connections by sending\n        # \"Connection: keep-alive\" in the HTTP headers.\n        if 'headers' not in kwargs:\n            kwargs['headers'] = {}\n        kwargs['headers']['connection'] = 'keep-alive'\n\n        try:\n            resp = self._con_pool.request(*args, **kwargs)\n        except urllib3.exceptions.TimeoutError:\n            raise TimedOut()\n        except urllib3.exceptions.HTTPError as error:\n            # HTTPError must come last as its the base urllib3 exception class\n            # TODO: do something smart here; for now just raise NetworkError\n            raise NetworkError('urllib3 HTTPError {0}'.format(error))\n\n        if 200 <= resp.status <= 299:\n            # 200-299 range are HTTP success statuses\n            return resp.data\n\n        try:\n            message = self._parse(resp.data)\n        except ValueError:\n            raise NetworkError('Unknown HTTPError {0}'.format(resp.status))\n\n        if resp.status in (401, 403):\n            raise Unauthorized()\n        elif resp.status == 400:\n            raise BadRequest(repr(message))\n        elif resp.status == 404:\n            raise InvalidToken()\n        elif resp.status == 502:\n            raise NetworkError('Bad Gateway')\n        else:\n            raise NetworkError('{0} ({1})'.format(message, resp.status))\n\n    def get(self, url, timeout=None):\n        \"\"\"Request an URL.\n\n        Args:\n            url (str): The web location we want to retrieve.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n        Returns:\n          A JSON object.\n\n        \"\"\"\n        urlopen_kwargs = {}\n\n        if timeout is not None:\n            urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)\n\n        result = self._request_wrapper('GET', url, **urlopen_kwargs)\n        return self._parse(result)\n\n    def post(self, url, data, timeout=None):\n        \"\"\"Request an URL.\n        Args:\n            url (str): The web location we want to retrieve.\n            data (dict[str, str]): A dict of key/value pairs. Note: On py2.7 value is unicode.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n        Returns:\n          A JSON object.\n\n        \"\"\"\n        urlopen_kwargs = {}\n\n        if timeout is not None:\n            urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)\n\n        if InputFile.is_inputfile(data):\n            data = InputFile(data)\n            result = self._request_wrapper(\n                'POST', url, body=data.to_form(), headers=data.headers, **urlopen_kwargs)\n        else:\n            data = json.dumps(data)\n            result = self._request_wrapper(\n                'POST',\n                url,\n                body=data.encode(),\n                headers={'Content-Type': 'application/json'},\n                **urlopen_kwargs)\n\n        return self._parse(result)\n\n    def retrieve(self, url, timeout=None):\n        \"\"\"Retrieve the contents of a file by its URL.\n\n        Args:\n            url (str): The web location we want to retrieve.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n        \"\"\"\n        urlopen_kwargs = {}\n        if timeout is not None:\n            urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)\n\n        return self._request_wrapper('GET', url, **urlopen_kwargs)\n\n    def download(self, url, filename, timeout=None):\n        \"\"\"Download a file by its URL.\n        Args:\n            url (str): The web location we want to retrieve.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n          filename:\n            The filename within the path to download the file.\n\n        \"\"\"\n        buf = self.retrieve(url, timeout=timeout)\n        with open(filename, 'wb') as fobj:\n            fobj.write(buf)\n", "path": "telegram/utils/request.py"}], "after_files": [{"content": "#!/usr/bin/env python\n\"\"\"The setup and build script for the python-telegram-bot library.\"\"\"\n\nimport codecs\nimport os\nfrom setuptools import setup, find_packages\n\n\ndef requirements():\n    \"\"\"Build the requirements list for this project\"\"\"\n    requirements_list = []\n\n    with open('requirements.txt') as requirements:\n        for install in requirements:\n            requirements_list.append(install.strip())\n\n    return requirements_list\n\n\nwith codecs.open('README.rst', 'r', 'utf-8') as fd:\n    fn = os.path.join('telegram', 'version.py')\n    with open(fn) as fh:\n        code = compile(fh.read(), fn, 'exec')\n        exec(code)\n\n    setup(name='python-telegram-bot',\n          version=__version__,\n          author='Leandro Toledo',\n          author_email='devs@python-telegram-bot.org',\n          license='LGPLv3',\n          url='https://python-telegram-bot.org/',\n          keywords='python telegram bot api wrapper',\n          description=\"We have made you a wrapper you can't refuse\",\n          long_description=fd.read(),\n          packages=find_packages(exclude=['tests*']),\n          install_requires=requirements(),\n          extras_require={\n              'json': 'ujson',\n              'socks': 'PySocks'\n          },\n          include_package_data=True,\n          classifiers=[\n              'Development Status :: 5 - Production/Stable',\n              'Intended Audience :: Developers',\n              'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',\n              'Operating System :: OS Independent',\n              'Topic :: Software Development :: Libraries :: Python Modules',\n              'Topic :: Communications :: Chat',\n              'Topic :: Internet',\n              'Programming Language :: Python',\n              'Programming Language :: Python :: 2',\n              'Programming Language :: Python :: 2.7',\n              'Programming Language :: Python :: 3',\n              'Programming Language :: Python :: 3.3',\n              'Programming Language :: Python :: 3.4',\n              'Programming Language :: Python :: 3.5',\n              'Programming Language :: Python :: 3.6'\n          ],)\n", "path": "setup.py"}, {"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2016\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains methods to make POST and GET requests\"\"\"\nimport os\nimport socket\nimport logging\n\ntry:\n    import ujson as json\nexcept ImportError:\n    import json\n\nimport certifi\nimport urllib3\nfrom urllib3.connection import HTTPConnection\nfrom urllib3.util.timeout import Timeout\ntry:\n    from urllib3.contrib.socks import SOCKSProxyManager\nexcept ImportError:\n    SOCKSProxyManager = None\n\nfrom telegram import (InputFile, TelegramError)\nfrom telegram.error import (Unauthorized, NetworkError, TimedOut, BadRequest, ChatMigrated,\n                            RetryAfter, InvalidToken)\n\nlogging.getLogger('urllib3').setLevel(logging.WARNING)\n\n\nclass Request(object):\n    \"\"\"\n    Helper class for python-telegram-bot which provides methods to perform POST & GET towards\n    telegram servers.\n\n    Args:\n        con_pool_size (int): Number of connections to keep in the connection pool.\n        proxy_url (str): The URL to the proxy server. For example: `http://127.0.0.1:3128`.\n        urllib3_proxy_kwargs (dict): Arbitrary arguments passed as-is to `urllib3.ProxyManager`.\n            This value will be ignored if proxy_url is not set.\n        connect_timeout (int|float): The maximum amount of time (in seconds) to wait for a\n            connection attempt to a server to succeed. None will set an infinite timeout for\n            connection attempts. (default: 5.)\n        read_timeout (int|float): The maximum amount of time (in seconds) to wait between\n            consecutive read operations for a response from the server. None will set an infinite\n            timeout. This value is usually overridden by the various ``telegram.Bot`` methods.\n            (default: 5.)\n\n    \"\"\"\n\n    def __init__(self,\n                 con_pool_size=1,\n                 proxy_url=None,\n                 urllib3_proxy_kwargs=None,\n                 connect_timeout=5.,\n                 read_timeout=5.):\n        if urllib3_proxy_kwargs is None:\n            urllib3_proxy_kwargs = dict()\n\n        self._connect_timeout = connect_timeout\n\n        kwargs = dict(\n            maxsize=con_pool_size,\n            cert_reqs='CERT_REQUIRED',\n            ca_certs=certifi.where(),\n            socket_options=HTTPConnection.default_socket_options + [\n                (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),\n            ],\n            timeout=urllib3.Timeout(\n                connect=self._connect_timeout, read=read_timeout),)\n\n        # Set a proxy according to the following order:\n        # * proxy defined in proxy_url (+ urllib3_proxy_kwargs)\n        # * proxy set in `HTTPS_PROXY` env. var.\n        # * proxy set in `https_proxy` env. var.\n        # * None (if no proxy is configured)\n\n        if not proxy_url:\n            proxy_url = os.environ.get('HTTPS_PROXY') or os.environ.get('https_proxy')\n\n        if not proxy_url:\n            mgr = urllib3.PoolManager(**kwargs)\n        else:\n            kwargs.update(urllib3_proxy_kwargs)\n            if proxy_url.startswith('socks'):\n                if not SOCKSProxyManager:\n                    raise RuntimeError('PySocks is missing')\n                mgr = SOCKSProxyManager(proxy_url, **kwargs)\n            else:\n                mgr = urllib3.proxy_from_url(proxy_url, **kwargs)\n                if mgr.proxy.auth:\n                    # TODO: what about other auth types?\n                    auth_hdrs = urllib3.make_headers(proxy_basic_auth=mgr.proxy.auth)\n                    mgr.proxy_headers.update(auth_hdrs)\n\n        self._con_pool = mgr\n\n    def stop(self):\n        self._con_pool.clear()\n\n    @staticmethod\n    def _parse(json_data):\n        \"\"\"Try and parse the JSON returned from Telegram.\n\n        Returns:\n            dict: A JSON parsed as Python dict with results - on error this dict will be empty.\n\n        \"\"\"\n        decoded_s = json_data.decode('utf-8')\n        try:\n            data = json.loads(decoded_s)\n        except ValueError:\n            raise TelegramError('Invalid server response')\n\n        if not data.get('ok'):\n            description = data.get('description')\n            parameters = data.get('parameters')\n            if parameters:\n                migrate_to_chat_id = parameters.get('migrate_to_chat_id')\n                if migrate_to_chat_id:\n                    raise ChatMigrated(migrate_to_chat_id)\n                retry_after = parameters.get('retry_after')\n                if retry_after:\n                    raise RetryAfter(retry_after)\n            if description:\n                return description\n\n        return data['result']\n\n    def _request_wrapper(self, *args, **kwargs):\n        \"\"\"Wraps urllib3 request for handling known exceptions.\n\n        Args:\n            args: unnamed arguments, passed to urllib3 request.\n            kwargs: keyword arguments, passed tp urllib3 request.\n\n        Returns:\n            str: A non-parsed JSON text.\n\n        Raises:\n            TelegramError\n\n        \"\"\"\n        # Make sure to hint Telegram servers that we reuse connections by sending\n        # \"Connection: keep-alive\" in the HTTP headers.\n        if 'headers' not in kwargs:\n            kwargs['headers'] = {}\n        kwargs['headers']['connection'] = 'keep-alive'\n\n        try:\n            resp = self._con_pool.request(*args, **kwargs)\n        except urllib3.exceptions.TimeoutError:\n            raise TimedOut()\n        except urllib3.exceptions.HTTPError as error:\n            # HTTPError must come last as its the base urllib3 exception class\n            # TODO: do something smart here; for now just raise NetworkError\n            raise NetworkError('urllib3 HTTPError {0}'.format(error))\n\n        if 200 <= resp.status <= 299:\n            # 200-299 range are HTTP success statuses\n            return resp.data\n\n        try:\n            message = self._parse(resp.data)\n        except ValueError:\n            raise NetworkError('Unknown HTTPError {0}'.format(resp.status))\n\n        if resp.status in (401, 403):\n            raise Unauthorized()\n        elif resp.status == 400:\n            raise BadRequest(repr(message))\n        elif resp.status == 404:\n            raise InvalidToken()\n        elif resp.status == 502:\n            raise NetworkError('Bad Gateway')\n        else:\n            raise NetworkError('{0} ({1})'.format(message, resp.status))\n\n    def get(self, url, timeout=None):\n        \"\"\"Request an URL.\n\n        Args:\n            url (str): The web location we want to retrieve.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n        Returns:\n          A JSON object.\n\n        \"\"\"\n        urlopen_kwargs = {}\n\n        if timeout is not None:\n            urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)\n\n        result = self._request_wrapper('GET', url, **urlopen_kwargs)\n        return self._parse(result)\n\n    def post(self, url, data, timeout=None):\n        \"\"\"Request an URL.\n        Args:\n            url (str): The web location we want to retrieve.\n            data (dict[str, str]): A dict of key/value pairs. Note: On py2.7 value is unicode.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n        Returns:\n          A JSON object.\n\n        \"\"\"\n        urlopen_kwargs = {}\n\n        if timeout is not None:\n            urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)\n\n        if InputFile.is_inputfile(data):\n            data = InputFile(data)\n            result = self._request_wrapper(\n                'POST', url, body=data.to_form(), headers=data.headers, **urlopen_kwargs)\n        else:\n            data = json.dumps(data)\n            result = self._request_wrapper(\n                'POST',\n                url,\n                body=data.encode(),\n                headers={'Content-Type': 'application/json'},\n                **urlopen_kwargs)\n\n        return self._parse(result)\n\n    def retrieve(self, url, timeout=None):\n        \"\"\"Retrieve the contents of a file by its URL.\n\n        Args:\n            url (str): The web location we want to retrieve.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n        \"\"\"\n        urlopen_kwargs = {}\n        if timeout is not None:\n            urlopen_kwargs['timeout'] = Timeout(read=timeout, connect=self._connect_timeout)\n\n        return self._request_wrapper('GET', url, **urlopen_kwargs)\n\n    def download(self, url, filename, timeout=None):\n        \"\"\"Download a file by its URL.\n        Args:\n            url (str): The web location we want to retrieve.\n            timeout (Optional[int|float]): If this value is specified, use it as the read timeout\n                from the server (instead of the one specified during creation of the connection\n                pool).\n\n          filename:\n            The filename within the path to download the file.\n\n        \"\"\"\n        buf = self.retrieve(url, timeout=timeout)\n        with open(filename, 'wb') as fobj:\n            fobj.write(buf)\n", "path": "telegram/utils/request.py"}]}