Skip to content

Commit cdb00f6

Browse files
Merge branch 'master' into update_license_year
2 parents 71f867f + 969b515 commit cdb00f6

File tree

9 files changed

+64
-46
lines changed

9 files changed

+64
-46
lines changed

.travis.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ fail_fast: true
1010
before_install:
1111
- pip install pycodestyle
1212
install:
13+
- pip install codecov
1314
- if [[ "$TRAVIS_PYTHON_VERSION" == 2.6* ]]; then travis_retry pip install unittest2; fi
1415
- if [[ "$TRAVIS_PYTHON_VERSION" == 2.6* ]]; then travis_retry pip uninstall -y pbr; fi
1516
- if [[ "$TRAVIS_PYTHON_VERSION" == "3.2" ]]; then travis_retry pip install coverage==3.7.1; fi
@@ -23,6 +24,7 @@ after_script:
2324
# Run pycodestyle
2425
- pycodestyle
2526
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then unit2 discover; else python -m unittest discover; fi
27+
- coverage run tests/test_unit.py
2628
notifications:
2729
hipchat:
2830
rooms:
@@ -33,7 +35,8 @@ notifications:
3335
<a href="https://github.com/sendgrid/%{repository}/commits/%{commit}">View on
3436
GitHub</a>'
3537
format: html
36-
notify: false
38+
after_success:
39+
- codecov
3740
env:
3841
global:
3942
- secure: 7j0Ox9ZQss0PewrhGih86Ro0pQJpv23Bb0uABJV7kKN/W37ofrG0m6joamf8EhDDleaPoIqfbARhUpAlqFZF0Uo/5rREqpKkmP4e1zuYMu20VbFv6PXwZ+7ByAuKXN2/Xs54MImlL1+RaduMPNRpbcfT1mdqJgSC+3tVcWodzuRG9RPzxtWYLe93QfwNHV/VMsDPDIY12FZTErbXd/hBCEQXep5rNfK+TtLIGn0ZnS7TktTcD0ld+0ruhunbDjnkpXPVSJDuLaGRpotq0oyaGifnjVM5gVubP+KCL3h24tIXjJ7uI36Eu3EuF4qsg0fmNjuM/WjgwZ9Ta4I2MHlXtFs//qMMArOw5AvPg25adrEwGO4Veh3I3tJGL7hJeM7AZX4rAycXiGIHvpP2G/nX6e/EqRrnFBDOStmBhxEaknLJ/p2Cv6AOvxTMKDo8y+tJY1jp3H1iwCBYyW6KuFKVPDYtu8VLxJunaqNX4LxiJN7VHgvTSgqImjzEy5tVxVt079ciyeznSKKGHLHDAl1ioQpmv/Oyas007A4PKJJAf73go8Yt+GM6qe3K6U3tIBKWL8e0cK1kejk9TLC0D9KXbmhmK81QzpBdQfkrveYi/kucVv0zdrGl+Uy8zcq+vYxceyCdDYcTxCS66bWNFTD2t1dML5gRpdNVVSc27ZM9wtA=

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Hello! Thank you for choosing to help contribute to one of the SendGrid open sou
1010
- [Testing Multiple Versions of Python](#testing-multiple-versions-of-python)
1111
- [Style Guidelines & Naming Conventions](#style-guidelines-and-naming-conventions)
1212
- [Creating a Pull Request](#creating-a-pull-request)
13+
- [Code Reviews](#code-reviews)
1314

1415
<a name="roadmap"></a>
1516
We use [Milestones](https://github.com/sendgrid/python-http-client/milestones) to help define current roadmaps, please feel free to grab an issue from the current milestone. Please indicate that you have begun work on it to avoid collisions. Once a PR is made, community review, comments, suggestions and additional PRs are welcomed and encouraged.
@@ -225,3 +226,7 @@ Please run your code through:
225226
with a clear title and description against the `master` branch. All tests must be passing before we will review the PR.
226227

227228
If you have any additional questions, please feel free to [email](mailto:[email protected]) us or create an issue in this repo.
229+
230+
<a name="code-reviews"></a>
231+
## Code Reviews
232+
If you can, please look at open PRs and review them. Give feedback and help us merge these PRs much faster! If you don't know how, Github has some great [information on how to review a Pull Request](https://help.github.com/articles/about-pull-request-reviews/).

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ Quick links:
110110
- [Bug Reports](https://github.com/sendgrid/python-http-client/blob/master/CONTRIBUTING.md#submit-a-bug-report)
111111
- [Sign the CLA to Create a Pull Request](https://github.com/sendgrid/python-http-client/blob/master/CONTRIBUTING.md#cla)
112112
- [Improvements to the Codebase](https://github.com/sendgrid/python-http-client/blob/master/CONTRIBUTING.md#improvements-to-the-codebase)
113+
- [Review Pull Requests](https://github.com/sendgrid/python-http-client/blob/master/CONTRIBUTING.md#code-reviews)
113114

114115
<a name="local_setup"></a>
115116

python_http_client/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from .client import Client
2-
from .exceptions import (
1+
from .client import Client # noqa
2+
from .exceptions import ( # noqa
33
HTTPError,
44
BadRequestsError,
55
UnauthorizedError,

python_http_client/client.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def __init__(self,
6464
request_headers=None,
6565
version=None,
6666
url_path=None,
67-
append_slash=False):
67+
append_slash=False,
68+
timeout=None):
6869
"""
6970
:param host: Base URL for the api. (e.g. https://api.sendgrid.com)
7071
:type host: string
@@ -88,6 +89,7 @@ def __init__(self,
8889
self.methods = ['delete', 'get', 'patch', 'post', 'put']
8990
# APPEND SLASH set
9091
self.append_slash = append_slash
92+
self.timeout = timeout
9193

9294
def _build_versioned_url(self, url):
9395
"""Subclass this function for your own needs.
@@ -124,7 +126,6 @@ def _build_url(self, query_params):
124126
url = self._build_versioned_url(url)
125127
else:
126128
url = self.host + url
127-
128129
return url
129130

130131
def _update_headers(self, request_headers):
@@ -148,20 +149,24 @@ def _build_client(self, name=None):
148149
version=self._version,
149150
request_headers=self.request_headers,
150151
url_path=url_path,
151-
append_slash=self.append_slash)
152+
append_slash=self.append_slash,
153+
timeout=self.timeout)
152154

153-
def _make_request(self, opener, request):
155+
def _make_request(self, opener, request, timeout=None):
154156
"""Make the API call and return the response. This is separated into
155157
it's own function, so we can mock it easily for testing.
156158
157159
:param opener:
158160
:type opener:
159161
:param request: url payload to request
160162
:type request: urllib.Request object
163+
:param timeout: timeout value or None
164+
:type timeout: float
161165
:return: urllib response
162166
"""
167+
timeout = timeout or self.timeout
163168
try:
164-
return opener.open(request)
169+
return opener.open(request, timeout=timeout)
165170
except HTTPError as err:
166171
exc = handle_error(err)
167172
exc.__cause__ = None
@@ -214,7 +219,6 @@ def http_request(*_, **kwargs):
214219
if 'request_body' not in kwargs:
215220
data = None
216221
else:
217-
218222
# Don't serialize to a JSON formatted str
219223
# if we don't have a JSON Content-Type
220224
if 'Content-Type' in self.request_headers:
@@ -241,7 +245,8 @@ def http_request(*_, **kwargs):
241245
if data and ('Content-Type' not in self.request_headers):
242246
request.add_header('Content-Type', 'application/json')
243247
request.get_method = lambda: method
244-
return Response(self._make_request(opener, request))
248+
timeout = kwargs.pop('timeout', None)
249+
return Response(self._make_request(opener, request, timeout=timeout))
245250
return http_request
246251
else:
247252
# Add a segment to the URL

register.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
import pypandoc
2-
import os
32

43

54
output = pypandoc.convert('README.md', 'rst')
65

76
with open('README.txt', 'w+') as f:
87
f.write(output)
98

10-
with open('./README.txt') as f:
11-
readme_rst = f.read()
9+
readme_rst = open('./README.txt').read()
1210

13-
replace = ('[SendGrid Logo]\n'
14-
'(https://uiux.s3.amazonaws.com/2016-logos/email-logo%402x.png)')
11+
replace = """\
12+
[SendGrid Logo]
13+
(https://uiux.s3.amazonaws.com/2016-logos/email-logo%402x.png)"""
1514

16-
replacement = ('|SendGrid Logo|\n\n.. |SendGrid Logo| image:: '
17-
'https://uiux.s3.amazonaws.com/2016-logos/email-logo%402x.png'
18-
'\n :target: https://www.sendgrid.com')
15+
replacement = """\
16+
|SendGrid Logo|
1917
20-
final_text = readme_rst.replace(replace, replacement)
18+
.. |SendGrid Logo| image:: \
19+
https://uiux.s3.amazonaws.com/2016-logos/email-logo%402x.png
20+
:target: https://www.sendgrid.com"""
2121

22+
final_text = readme_rst.replace(replace, replacement)
2223
with open('./README.txt', 'w') as f:
2324
f.write(final_text)

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
long_description = open('README.txt').read()
99

1010

11-
def getRequires():
11+
def get_requires():
1212
deps = []
1313
if (2, 6) <= sys.version_info < (2, 7):
1414
deps.append('unittest2')
@@ -28,7 +28,7 @@ def getRequires():
2828
license='MIT',
2929
description='HTTP REST client, simplified for Python',
3030
long_description=long_description,
31-
install_requires=getRequires(),
31+
install_requires=get_requires(),
3232
keywords=[
3333
'REST',
3434
'HTTP',

tests/test_daterange.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ def setUp(self):
1414
'../LICENSE.txt')
1515
self.pattern = 'Copyright (c) 2012 - %s SendGrid, Inc.' % (
1616
time.strftime("%Y"))
17-
self.licensefile = open(self.openlicensefile).read()
17+
fh = open(self.openlicensefile)
18+
self.licensefile = fh.read()
19+
fh.close()
1820

1921
def test__daterange(self):
2022
self.assertTrue(self.pattern in self.licensefile)
23+

tests/test_unit.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import os
21
import pickle
3-
from os import path
2+
43
try:
54
import unittest2 as unittest
65
except ImportError:
76
import unittest
8-
from python_http_client.client import Client, Response
7+
from python_http_client.client import Client
98
from python_http_client.exceptions import (
109
handle_error,
1110
HTTPError,
@@ -15,15 +14,13 @@
1514
ServiceUnavailableError
1615
)
1716

18-
1917
try:
2018
# Python 3
2119
import urllib.request as urllib
2220
except ImportError:
2321
# Python 2
2422
import urllib2 as urllib
2523

26-
2724
try:
2825
basestring
2926
except NameError:
@@ -58,13 +55,12 @@ def read(self):
5855

5956
class MockClient(Client):
6057

61-
def __init__(self, host, response_code):
58+
def __init__(self, host, response_code, timeout=None):
6259
self.response_code = 200
6360
Client.__init__(self, host)
6461

65-
def _make_request(self, opener, request):
66-
67-
if 200 <= self.response_code < 299: # if successful code
62+
def _make_request(self, opener, request, timeout=None):
63+
if 200 <= self.response_code < 299: # if successful code
6864
return MockResponse(self.response_code)
6965
else:
7066
raise handle_error(MockException(self.response_code))
@@ -74,12 +70,11 @@ class TestClient(unittest.TestCase):
7470

7571
def setUp(self):
7672
self.host = 'http://api.test.com'
77-
self.client = Client(host=self.host)
78-
self.api_key = 'SENDGRID_API_KEY'
73+
self.api_key = "SENDGRID_API_KEY"
7974
self.request_headers = {
80-
'Content-Type': 'application/json',
81-
'Authorization': 'Bearer ' + self.api_key
82-
}
75+
'Content-Type': 'application/json',
76+
'Authorization': 'Bearer ' + self.api_key
77+
}
8378
self.client = Client(host=self.host,
8479
request_headers=self.request_headers,
8580
version=3)
@@ -88,6 +83,7 @@ def test__init__(self):
8883
default_client = Client(host=self.host)
8984
self.assertEqual(default_client.host, self.host)
9085
self.assertEqual(default_client.request_headers, {})
86+
self.assertIs(default_client.timeout, None)
9187
methods = ['delete', 'get', 'patch', 'post', 'put']
9288
self.assertEqual(default_client.methods, methods)
9389
self.assertEqual(default_client._version, None)
@@ -97,13 +93,15 @@ def test__init__(self):
9793
version = 3
9894
client = Client(host=self.host,
9995
request_headers=request_headers,
100-
version=version)
96+
version=version,
97+
timeout=10)
10198
self.assertEqual(client.host, self.host)
10299
self.assertEqual(client.request_headers, request_headers)
103100
methods = ['delete', 'get', 'patch', 'post', 'put']
104101
self.assertEqual(client.methods, methods)
105102
self.assertEqual(client._version, 3)
106103
self.assertEqual(client._url_path, [])
104+
self.assertEqual(client.timeout, 10)
107105

108106
def test__build_versioned_url(self):
109107
url = '/api_keys?hello=1&world=2'
@@ -116,13 +114,12 @@ def test__build_url(self):
116114
self.client._url_path = self.client._url_path + ['there']
117115
self.client._url_path = self.client._url_path + [1]
118116
self.client._version = 3
119-
120-
url = '{0}/v{1}{2}'.format(self.host,
121-
str(self.client._version),
122-
'/here/there/1?hello=0&' +
123-
'world=1&ztest=0&ztest=1')
117+
url = '{0}/v{1}{2}'.format(
118+
self.host,
119+
str(self.client._version),
120+
'/here/there/1?hello=0&world=1&ztest=0&ztest=1'
121+
)
124122
query_params = {'hello': 0, 'world': 1, 'ztest': [0, 1]}
125-
126123
built_url = self.client._build_url(query_params)
127124
self.assertEqual(built_url, url)
128125

@@ -154,7 +151,7 @@ def test__getattr__(self):
154151
self.assertEqual(client._version, 3)
155152

156153
# Test GET
157-
mock_client._url_path+['test']
154+
mock_client._url_path + ['test']
158155
r = mock_client.get()
159156
self.assertEqual(r.status_code, 200)
160157

@@ -191,11 +188,14 @@ def test__getattr__(self):
191188
mock_client.response_code = 523
192189
self.assertRaises(HTTPError, mock_client.delete)
193190

194-
195191
def test_client_pickle_unpickle(self):
196192
pickled_client = pickle.dumps(self.client)
197193
unpickled_client = pickle.loads(pickled_client)
198-
self.assertDictEqual(self.client.__dict__, unpickled_client.__dict__, "original client and unpickled client must have the same state")
194+
self.assertDictEqual(
195+
self.client.__dict__,
196+
unpickled_client.__dict__,
197+
"original client and unpickled client must have the same state"
198+
)
199199

200200

201201
if __name__ == '__main__':

0 commit comments

Comments
 (0)