Skip to content

Commit

Permalink
Remove Py3.4 compatibility and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
alfred82santa committed May 15, 2017
1 parent 7bf5854 commit b964407
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 624 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: python
python:
- "3.4"
- "3.5"
- "3.6"
# command to install dependencies
install:
- make requirements-test
Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ v0.6.0

- Added new hook ``close`` in order to notify plugins that client is going to close.

- Removed compatibility with Python 3.4.


v0.5.4
------
Expand Down
123 changes: 56 additions & 67 deletions service_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from asyncio import coroutine, get_event_loop
from asyncio import get_event_loop
from asyncio.tasks import Task
from urllib.parse import urlparse, urlunsplit

Expand All @@ -14,6 +14,7 @@


class ServiceClient:

def __init__(self, name='GenericService', spec=None, plugins=None, config=None,
parser=None, serializer=None, base_path='', loop=None, logger=None):
self._plugins = []
Expand Down Expand Up @@ -44,25 +45,24 @@ def create_response(self, *args, **kwargs):

return response

@coroutine
def call(self, endpoint, payload=None, **kwargs):
async def call(self, endpoint, payload=None, **kwargs):
self.logger.debug("Calling service {0}...".format(endpoint))
endpoint_desc = self.spec[endpoint].copy()
endpoint_desc['endpoint'] = endpoint

request_params = kwargs
session = yield from self.prepare_session(endpoint_desc, request_params)
session = await self.prepare_session(endpoint_desc, request_params)

request_params['url'] = URL((yield from self.generate_path(endpoint_desc, session, request_params)))
request_params['url'] = URL((await self.generate_path(endpoint_desc, session, request_params)))
request_params['method'] = endpoint_desc.get('method', 'GET').upper()

yield from self.prepare_request_params(endpoint_desc, session, request_params)
await self.prepare_request_params(endpoint_desc, session, request_params)

self.logger.info("Calling service {0} using {1} {2}".format(endpoint,
request_params['method'],
request_params['url']))

payload = yield from self.prepare_payload(endpoint_desc, session, request_params, payload)
payload = await self.prepare_payload(endpoint_desc, session, request_params, payload)
try:
if request_params['method'] not in ['GET', 'DELETE']:
try:
Expand All @@ -77,18 +77,19 @@ def call(self, endpoint, payload=None, **kwargs):
endpoint_desc=endpoint_desc,
request_params=request_params)

yield from self.before_request(endpoint_desc, session, request_params)
await self.before_request(endpoint_desc, session, request_params)
task = Task.current_task(loop=self.loop)
task.session = session
task.endpoint_desc = endpoint_desc
task.request_params = request_params
response = yield from session.request(**request_params)

response = await session.request(**request_params)
except Exception as e:
self.logger.warn("Exception calling service {0}: {1}".format(endpoint, e))
yield from self.on_exception(endpoint_desc, session, request_params, e)
await self.on_exception(endpoint_desc, session, request_params, e)
raise e

yield from self.on_response(endpoint_desc, session, request_params, response)
await self.on_response(endpoint_desc, session, request_params, response)

try:
if endpoint_desc['stream_response']:
Expand All @@ -97,32 +98,30 @@ def call(self, endpoint, payload=None, **kwargs):
pass

try:
data = yield from response.read()
yield from self.on_read(endpoint_desc, session, request_params, response)
data = await response.read()
await self.on_read(endpoint_desc, session, request_params, response)
self.logger.info("Parsing response from {0}...".format(endpoint))
response.data = self.parser(data,
session=session,
endpoint_desc=endpoint_desc,
response=response)
yield from self.on_parsed_response(endpoint_desc, session, request_params, response)
await self.on_parsed_response(endpoint_desc, session, request_params, response)
except Exception as e:
self.logger.warn("[Response code: {0}] Exception parsing response from service "
"{1}: {2}".format(response.status, endpoint, e))
yield from self.on_parse_exception(endpoint_desc, session, request_params, response, e)
await self.on_parse_exception(endpoint_desc, session, request_params, response, e)
e.response = response
raise e

return response

@coroutine
def prepare_session(self, endpoint_desc, request_params):
async def prepare_session(self, endpoint_desc, request_params):
session = ObjectWrapper(self.session)
yield from self._execute_plugin_hooks('prepare_session', endpoint_desc=endpoint_desc, session=session,
request_params=request_params)
await self._execute_plugin_hooks('prepare_session', endpoint_desc=endpoint_desc, session=session,
request_params=request_params)
return session

@coroutine
def generate_path(self, endpoint_desc, session, request_params):
async def generate_path(self, endpoint_desc, session, request_params):
path = endpoint_desc.get('path', '')
url = list(urlparse(self.base_path))
url[2] = '/'.join([url[2].rstrip('/'), path.lstrip('/')])
Expand All @@ -133,72 +132,63 @@ def generate_path(self, endpoint_desc, session, request_params):
self.logger.debug("Calling {0} plugin hooks...".format('prepare_path'))
for func in hooks:
try:
path = yield from func(endpoint_desc=endpoint_desc, session=session,
request_params=request_params, path=path)
path = await func(endpoint_desc=endpoint_desc, session=session,
request_params=request_params, path=path)
except Exception as ex: # pragma: no cover
self.logger.error("Exception executing {0}".format(repr(func)))
self.logger.exception(ex)
raise

return path

@coroutine
def prepare_request_params(self, endpoint_desc, session, request_params):
yield from self._execute_plugin_hooks('prepare_request_params', endpoint_desc=endpoint_desc,
session=session, request_params=request_params)
async def prepare_request_params(self, endpoint_desc, session, request_params):
await self._execute_plugin_hooks('prepare_request_params', endpoint_desc=endpoint_desc,
session=session, request_params=request_params)

@coroutine
def prepare_payload(self, endpoint_desc, session, request_params, payload):
async def prepare_payload(self, endpoint_desc, session, request_params, payload):
hooks = [getattr(plugin, 'prepare_payload') for plugin in self._plugins
if hasattr(plugin, 'prepare_payload')]
self.logger.debug("Calling {0} plugin hooks...".format('prepare_payload'))
for func in hooks:
try:
payload = yield from func(endpoint_desc=endpoint_desc, session=session,
request_params=request_params, payload=payload)
payload = await func(endpoint_desc=endpoint_desc, session=session,
request_params=request_params, payload=payload)
except Exception as ex: # pragma: no cover
self.logger.error("Exception executing {0}".format(repr(func)))
self.logger.exception(ex)
raise
return payload

@coroutine
def before_request(self, endpoint_desc, session, request_params):
yield from self._execute_plugin_hooks('before_request', endpoint_desc=endpoint_desc,
session=session, request_params=request_params)

@coroutine
def on_exception(self, endpoint_desc, session, request_params, ex):
yield from self._execute_plugin_hooks('on_exception', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, ex=ex)

@coroutine
def on_response(self, endpoint_desc, session, request_params, response):
yield from self._execute_plugin_hooks('on_response', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, response=response)

@coroutine
def on_read(self, endpoint_desc, session, request_params, response):
yield from self._execute_plugin_hooks('on_read', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, response=response)

@coroutine
def on_parse_exception(self, endpoint_desc, session, request_params, response, ex):
yield from self._execute_plugin_hooks('on_parse_exception', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, response=response, ex=ex)

@coroutine
def on_parsed_response(self, endpoint_desc, session, request_params, response):
yield from self._execute_plugin_hooks('on_parsed_response', endpoint_desc=endpoint_desc, session=session,
request_params=request_params, response=response)

@coroutine
def _execute_plugin_hooks(self, hook, *args, **kwargs):
async def before_request(self, endpoint_desc, session, request_params):
await self._execute_plugin_hooks('before_request', endpoint_desc=endpoint_desc,
session=session, request_params=request_params)

async def on_exception(self, endpoint_desc, session, request_params, ex):
await self._execute_plugin_hooks('on_exception', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, ex=ex)

async def on_response(self, endpoint_desc, session, request_params, response):
await self._execute_plugin_hooks('on_response', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, response=response)

async def on_read(self, endpoint_desc, session, request_params, response):
await self._execute_plugin_hooks('on_read', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, response=response)

async def on_parse_exception(self, endpoint_desc, session, request_params, response, ex):
await self._execute_plugin_hooks('on_parse_exception', endpoint_desc=endpoint_desc,
session=session, request_params=request_params, response=response, ex=ex)

async def on_parsed_response(self, endpoint_desc, session, request_params, response):
await self._execute_plugin_hooks('on_parsed_response', endpoint_desc=endpoint_desc, session=session,
request_params=request_params, response=response)

async def _execute_plugin_hooks(self, hook, *args, **kwargs):
hooks = [getattr(plugin, hook) for plugin in self._plugins if hasattr(plugin, hook)]
self.logger.debug("Calling {0} plugin hooks...".format(hook))
for func in hooks:
try:
yield from func(*args, **kwargs)
await func(*args, **kwargs)
except Exception as ex: # pragma: no cover
self.logger.error("Exception executing {0}".format(repr(func)))
self.logger.exception(ex)
Expand All @@ -224,9 +214,8 @@ def add_plugins(self, plugins):

def __getattr__(self, item):

@coroutine
def wrap(*args, **kwargs):
return self.call(item, *args, **kwargs)
async def wrap(*args, **kwargs):
return await self.call(item, *args, **kwargs)

return wrap

Expand Down
31 changes: 10 additions & 21 deletions service_client/mocks.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from asyncio import get_event_loop

from aiohttp.client_reqrep import ClientResponse
from multidict import CIMultiDict
from functools import wraps
from asyncio import coroutine, get_event_loop
from dirty_loader import LoaderNamespaceReversedCached
from functools import wraps
from multidict import CIMultiDict
from yarl import URL

from .plugins import BasePlugin
Expand All @@ -13,7 +14,6 @@ class NoMock(Exception):


class BaseMockDefinition:

def __init__(self, mock_manager, service_name=None, endpoint=None, offset=0, limit=1):
self.mock_manager = mock_manager
self.service_name = service_name
Expand All @@ -23,10 +23,9 @@ def __init__(self, mock_manager, service_name=None, endpoint=None, offset=0, lim

def __call__(self, func):
@wraps(func)
@coroutine
def inner(*args, **kwargs):
async def inner(*args, **kwargs):
with self:
yield from func(*args, **kwargs)
await func(*args, **kwargs)

return inner

Expand All @@ -38,21 +37,18 @@ def __exit__(self, exc_type, exc_val, exc_tb):


class PatchMockDescDefinition(BaseMockDefinition):

def __init__(self, patch, *args, **kwargs):
super(PatchMockDescDefinition, self).__init__(*args, **kwargs)
self.patch = patch


class UseMockDefinition(BaseMockDefinition):

def __init__(self, mock, *args, **kwargs):
super(UseMockDefinition, self).__init__(*args, **kwargs)
self.mock = mock


class MockManager:

def __init__(self):
self.mocks = []

Expand Down Expand Up @@ -133,7 +129,6 @@ def next_mock(self, service_name, endpoint):


class Mock(BasePlugin):

def __init__(self, namespaces=None):

self.loader = LoaderNamespaceReversedCached()
Expand Down Expand Up @@ -163,8 +158,7 @@ def _create_mock(self, endpoint_desc, session, request_params, mock_desc, loop):
request_params, mock_desc,
loop=loop)

@coroutine
def prepare_session(self, endpoint_desc, session, request_params):
async def prepare_session(self, endpoint_desc, session, request_params):
mock_desc = endpoint_desc.get('mock', {})
session.override_attr('request', self._create_mock(endpoint_desc,
session,
Expand All @@ -179,7 +173,6 @@ def prepare_session(self, endpoint_desc, session, request_params):


class BaseMock:

def __init__(self, endpoint_desc, session, request_params,
mock_desc, loop=None):
self.endpoint_desc = endpoint_desc
Expand All @@ -188,8 +181,7 @@ def __init__(self, endpoint_desc, session, request_params,
self.mock_desc = mock_desc
self.loop = loop or get_event_loop()

@coroutine
def __call__(self, *args, **kwargs):
async def __call__(self, *args, **kwargs):
args = list(args)
try:
method = kwargs['method']
Expand All @@ -210,20 +202,17 @@ def __call__(self, *args, **kwargs):
self.response.status = self.mock_desc.get('status', 200)
self.response.headers = CIMultiDict(self.mock_desc.get('headers', {}))

yield from self.prepare_response()
await self.prepare_response()

return self.response


class BaseFileMock(BaseMock):

@coroutine
def prepare_response(self):
async def prepare_response(self):
filename = self.mock_desc['file']
self.response._content = self.load_file(filename)


class RawFileMock(BaseFileMock):

def load_file(self, filename):
return open(filename, "rb").read()
Loading

0 comments on commit b964407

Please sign in to comment.