Skip to content

Commit

Permalink
Merge branch 'Kyria-transport-adaptor-param'
Browse files Browse the repository at this point in the history
  • Loading branch information
Henk Kraal committed Nov 10, 2016
2 parents 1d51b36 + 55018e6 commit 26d72a4
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 23 deletions.
6 changes: 4 additions & 2 deletions pycrest/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ def __init__(self, url, code, json_response):

def __str__(self):
if 'error' in self.response:
return 'HTTP Error %s: %s' % (self.status_code, self.response['error'])
return 'HTTP Error %s: %s' % (self.status_code,
self.response['error'])
elif 'message' in self.response:
return 'HTTP Error %s: %s' % (self.status_code, self.response['message'])
return 'HTTP Error %s: %s' % (self.status_code,
self.response['message'])
else:
return 'HTTP Error %s' % (self.status_code)

Expand Down
50 changes: 29 additions & 21 deletions pycrest/eve.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pycrest import version
from pycrest.compat import bytes_, text_
from pycrest.errors import APIException, UnsupportedHTTPMethodException

from requests.adapters import HTTPAdapter
try:
from urllib.parse import urlparse, urlunparse, parse_qsl
except ImportError: # pragma: no cover
Expand All @@ -28,6 +28,7 @@ def __init__(
self,
additional_headers=None,
user_agent=None,
transport_adapter=None,
**kwargs):
'''Initialises a PyCrest object
Expand All @@ -44,6 +45,10 @@ def __init__(
if user_agent is None:
user_agent = "PyCrest/{0} +https://github.com/pycrest/PyCrest"\
.format(version)
if isinstance(transport_adapter, HTTPAdapter):
session.mount('http://', transport_adapter)
session.mount('https://', transport_adapter)

session.headers.update({
"User-Agent": user_agent,
"Accept": "application/json",
Expand Down Expand Up @@ -84,7 +89,7 @@ def _parse_parameters(self, resource, params):
def get(self, resource, params={}, caching=True):
logger.debug('Getting resource %s', resource)
resource, prms = self._parse_parameters(resource, params)

# check cache
key = (
resource, frozenset(
Expand All @@ -109,14 +114,13 @@ def get(self, resource, params={}, caching=True):

logger.debug('Getting resource %s (params=%s)', resource, prms)
res = self._session.get(resource, params=prms)

if res.status_code != 200:
raise APIException(
resource,
res.status_code,
res.json()
)


ret = res.json()

Expand All @@ -125,7 +129,7 @@ def get(self, resource, params={}, caching=True):
resource, frozenset(
self._session.headers.items()), frozenset(
prms.items()))

expires = self._get_expires(res)
if expires > 0 and caching:
self.cache.put(
Expand All @@ -134,7 +138,7 @@ def get(self, resource, params={}, caching=True):

return ret

#post is not idempotent so there should be no caching
# post is not idempotent so there should be no caching
def post(self, resource, data={}):
logger.debug('Posting resource %s (data=%s)', resource, data)
res = self._session.post(resource, data=data)
Expand All @@ -147,7 +151,7 @@ def post(self, resource, data={}):

return {}

#put is not idempotent so there should be no caching
# put is not idempotent so there should be no caching
def put(self, resource, data={}):
logger.debug('Putting resource %s (data=%s)', resource, data)
res = self._session.put(resource, data=data)
Expand All @@ -160,7 +164,7 @@ def put(self, resource, data={}):

return {}

#delete is not idempotent so there should be no caching
# delete is not idempotent so there should be no caching
def delete(self, resource):
logger.debug('Deleting resource %s', resource)
res = self._session.delete(resource)
Expand Down Expand Up @@ -205,7 +209,9 @@ def __init__(self, **kwargs):

def __call__(self, caching=True):
if not self._data:
self._data = APIObject(self.get(self._endpoint, caching=caching), self)
self._data = APIObject(self.get(self._endpoint,
caching=caching),
self)
return self._data

def __getattr__(self, item):
Expand Down Expand Up @@ -328,6 +334,7 @@ def get(self, resource, params={}, caching=True):
self.refresh()
return super(self.__class__, self).get(resource, params, caching)


class APIObject(object):

def __init__(self, parent, connection):
Expand Down Expand Up @@ -357,8 +364,6 @@ def __getattr__(self, item):
return self._dict[item]
raise AttributeError(item)



def __call__(self, **kwargs):
"""carries out a CREST request
Expand All @@ -370,32 +375,35 @@ def __call__(self, **kwargs):
data contains any arguments that will be passed with the request -
it could be a dictionary which contains parameters
and is passed via the url for 'get' requests and as form-encoded
data for 'post' or 'put' requests. It could also be a string if
another format of data (e.g. via json.dumps()) must be passed in
data for 'post' or 'put' requests. It could also be a string if
another format of data (e.g. via json.dumps()) must be passed in
a 'post' or 'put' request. This parameter has no effect on
'delete' requests.
"""

# Caching is now handled by APIConnection
if 'href' in self._dict:
method = kwargs.pop('method', 'get')#default to get: historic behaviour
method = kwargs.pop('method', 'get') # default to get: historic behaviour
data = kwargs.pop('data', {})
caching = kwargs.pop('caching', True) # default caching to true, for get requests
caching = kwargs.pop('caching', True) # default caching to true, for get requests

#retain compatibility with historic method of passing parameters.
#Slightly unsatisfactory - what if data is dict-like but not a dict?
# retain compatibility with historic method of passing parameters.
# Slightly unsatisfactory - what if data is dict-like but not a dict?
if isinstance(data, dict):
for arg in kwargs:
for arg in kwargs:
data[arg] = kwargs[arg]

if method == 'post':
return APIObject(self.connection.post(self._dict['href'], data=data), self.connection)
elif method == 'put':
return APIObject(self.connection.put(self._dict['href'], data=data), self.connection)
elif method == 'delete':
return APIObject(self.connection.delete(self._dict['href'] ), self.connection)
elif method == 'get':
return APIObject(self.connection.get(self._dict['href'], params=data, caching=caching), self.connection)
return APIObject(self.connection.delete(self._dict['href']), self.connection)
elif method == 'get':
return APIObject(self.connection.get(self._dict['href'],
params=data,
caching=caching),
self.connection)
else:
raise UnsupportedHTTPMethodException(method)
else:
Expand Down
30 changes: 30 additions & 0 deletions tests/test_pycrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import errno
from pycrest.errors import APIException, UnsupportedHTTPMethodException
from requests.models import PreparedRequest
from requests.adapters import HTTPAdapter
import unittest

try:
Expand Down Expand Up @@ -261,6 +262,35 @@ def check_custom_headers(url, request):
with httmock.HTTMock(check_custom_headers):
EVE(additional_headers={'PyCrest-Testing': True})

def test_custom_transport_adapter(self):
""" Check if the transport adapter is the one expected (especially if we set it) """
class TestHttpAdapter(HTTPAdapter):
def __init__(self, *args, **kwargs):
super(TestHttpAdapter, self).__init__(*args, **kwargs)

class FakeHttpAdapter(object):
def __init__(self, *args, **kwargs):
pass

eve = EVE()
self.assertTrue(isinstance(eve._session.get_adapter('http://'), HTTPAdapter))
self.assertTrue(isinstance(eve._session.get_adapter('https://'), HTTPAdapter))
self.assertFalse(isinstance(eve._session.get_adapter('http://'), TestHttpAdapter))
self.assertFalse(isinstance(eve._session.get_adapter('https://'), TestHttpAdapter))

eve = EVE(transport_adapter=TestHttpAdapter())
self.assertTrue(isinstance(eve._session.get_adapter('http://'), TestHttpAdapter))
self.assertTrue(isinstance(eve._session.get_adapter('https://'), TestHttpAdapter))

# check that the wrong httpadapter is not used
eve = EVE(transport_adapter=FakeHttpAdapter())
self.assertTrue(isinstance(eve._session.get_adapter('http://'), HTTPAdapter))
self.assertFalse(isinstance(eve._session.get_adapter('http://'), FakeHttpAdapter))

eve = EVE(transport_adapter='')
self.assertTrue(isinstance(eve._session.get_adapter('http://'), HTTPAdapter))


def test_default_cache(self):
self.assertTrue(isinstance(self.api.cache, DictCache))

Expand Down

0 comments on commit 26d72a4

Please sign in to comment.