Skip to content

Commit 31b6027

Browse files
Merge branch 'master' into master
2 parents 98a80d7 + 397b3a6 commit 31b6027

File tree

4 files changed

+63
-36
lines changed

4 files changed

+63
-36
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ matrix:
1515
fail_fast: true
1616
before_install:
1717
- pip install pycodestyle
18+
- if [[ "$TRAVIS_PYTHON_VERSION" == 2.7* ]]; then pip install mock; fi
1819
install:
1920
- pip install codecov
2021
- travis_retry pip install coverage

python_http_client/client.py

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ def to_dict(self):
7373
class Client(object):
7474
"""Quickly and easily access any REST or REST-like API."""
7575

76+
# These are the supported HTTP verbs
77+
methods = {'delete', 'get', 'patch', 'post', 'put'}
78+
7679
def __init__(self,
7780
host,
7881
request_headers=None,
@@ -99,8 +102,6 @@ def __init__(self,
99102
self._version = version
100103
# _url_path keeps track of the dynamically built url
101104
self._url_path = url_path or []
102-
# These are the supported HTTP verbs
103-
self.methods = ['delete', 'get', 'patch', 'post', 'put']
104105
# APPEND SLASH set
105106
self.append_slash = append_slash
106107
self.timeout = timeout
@@ -227,42 +228,49 @@ def get_version(*args, **kwargs):
227228
if name in self.methods:
228229
method = name.upper()
229230

230-
def http_request(*_, **kwargs):
231+
def http_request(
232+
request_body=None,
233+
query_params=None,
234+
request_headers=None,
235+
timeout=None,
236+
**_):
231237
"""Make the API call
232-
:param args: unused
238+
:param timeout: HTTP request timeout. Will be propagated to
239+
urllib client
240+
:type timeout: float
241+
:param request_headers: HTTP headers. Will be merged into
242+
current client object state
243+
:type request_headers: dict
244+
:param query_params: HTTP query parameters
245+
:type query_params: dict
246+
:param request_body: HTTP request body
247+
:type request_body: string or json-serializable object
233248
:param kwargs:
234-
:return: Client object
249+
:return: Response object
235250
"""
236-
if 'request_headers' in kwargs:
237-
self._update_headers(kwargs['request_headers'])
238-
if 'request_body' not in kwargs:
251+
if request_headers:
252+
self._update_headers(request_headers)
253+
254+
if request_body is None:
239255
data = None
240256
else:
241257
# Don't serialize to a JSON formatted str
242258
# if we don't have a JSON Content-Type
243-
if 'Content-Type' in self.request_headers:
244-
if self.request_headers['Content-Type'] != \
245-
'application/json':
246-
data = kwargs['request_body'].encode('utf-8')
247-
else:
248-
data = json.dumps(
249-
kwargs['request_body']).encode('utf-8')
259+
if 'Content-Type' in self.request_headers and \
260+
self.request_headers['Content-Type'] != \
261+
'application/json':
262+
data = request_body.encode('utf-8')
250263
else:
251-
data = json.dumps(
252-
kwargs['request_body']).encode('utf-8')
253-
254-
if 'query_params' in kwargs:
255-
params = kwargs['query_params']
256-
else:
257-
params = None
264+
self.request_headers.setdefault(
265+
'Content-Type', 'application/json')
266+
data = json.dumps(request_body).encode('utf-8')
258267

259268
opener = urllib.build_opener()
260-
request = urllib.Request(self._build_url(params), data=data)
261-
if self.request_headers:
262-
for key, value in self.request_headers.items():
263-
request.add_header(key, value)
264-
if data and ('Content-Type' not in self.request_headers):
265-
request.add_header('Content-Type', 'application/json')
269+
request = urllib.Request(
270+
self._build_url(query_params),
271+
headers=self.request_headers,
272+
data=data,
273+
)
266274
request.get_method = lambda: method
267275
timeout = kwargs.pop('timeout', None)
268276
_logger.info('{method} Request: {url}'.format(

tests/test_daterange.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import time
33
import unittest
4+
import warnings
45

56

67
class DateRangeTest(unittest.TestCase):
@@ -15,4 +16,7 @@ def setUp(self):
1516
fh.close()
1617

1718
def test__daterange(self):
18-
self.assertIn(self.pattern, self.licensefile)
19+
try:
20+
self.assertIn(self.pattern, self.licensefile)
21+
except AssertionError:
22+
warnings.warn("License file does not contain a current year!")

tests/test_unit.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@
33

44
from python_http_client.client import Client
55
from python_http_client.exceptions import (
6-
handle_error,
7-
HTTPError,
8-
BadRequestsError,
6+
BadRequestsError, HTTPError,
97
NotFoundError,
8+
ServiceUnavailableError,
109
UnsupportedMediaTypeError,
11-
ServiceUnavailableError
10+
handle_error
1211
)
1312

1413
try:
1514
# Python 3
1615
import urllib.request as urllib
16+
from unittest import mock
1717
except ImportError:
1818
# Python 2
1919
import urllib2 as urllib
20+
import mock
2021

2122
try:
2223
basestring
@@ -81,7 +82,7 @@ def test__init__(self):
8182
self.assertEqual(default_client.host, self.host)
8283
self.assertEqual(default_client.request_headers, {})
8384
self.assertIs(default_client.timeout, None)
84-
methods = ['delete', 'get', 'patch', 'post', 'put']
85+
methods = {'delete', 'get', 'patch', 'post', 'put'}
8586
self.assertEqual(default_client.methods, methods)
8687
self.assertIsNone(default_client._version)
8788
self.assertEqual(default_client._url_path, [])
@@ -94,7 +95,7 @@ def test__init__(self):
9495
timeout=10)
9596
self.assertEqual(client.host, self.host)
9697
self.assertEqual(client.request_headers, request_headers)
97-
methods = ['delete', 'get', 'patch', 'post', 'put']
98+
methods = {'delete', 'get', 'patch', 'post', 'put'}
9899
self.assertEqual(client.methods, methods)
99100
self.assertEqual(client._version, 3)
100101
self.assertEqual(client._url_path, [])
@@ -120,6 +121,19 @@ def test__build_url(self):
120121
built_url = self.client._build_url(query_params)
121122
self.assertEqual(built_url, url)
122123

124+
@mock.patch('python_http_client.client.Client._make_request')
125+
def test__urllib_headers(self, maker):
126+
self.client._update_headers({'X-test': 'Test'})
127+
self.client.get()
128+
request = maker.call_args[0][1]
129+
self.assertIn('X-test', request.headers)
130+
131+
@mock.patch('python_http_client.client.Client._make_request')
132+
def test__urllib_method(self, maker):
133+
self.client.delete()
134+
request = maker.call_args[0][1]
135+
self.assertEqual(request.get_method(), 'DELETE')
136+
123137
def test__update_headers(self):
124138
request_headers = {'X-Test': 'Test'}
125139
self.client._update_headers(request_headers)
@@ -148,7 +162,7 @@ def test__getattr__(self):
148162
self.assertEqual(client._version, 3)
149163

150164
# Test GET
151-
mock_client._url_path + ['test']
165+
mock_client._url_path += ['test']
152166
r = mock_client.get()
153167
self.assertEqual(r.status_code, 200)
154168
self.assertEqual(r.method, 'GET')

0 commit comments

Comments
 (0)