Skip to content

Commit

Permalink
Added factories & spec loaders
Browse files Browse the repository at this point in the history
  • Loading branch information
alfred82santa committed Jun 6, 2016
1 parent 873fc2e commit b232382
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 2 deletions.
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ In order to send a payload you must use ``payload`` keyword on call:
Changelog
=========

v0.5.0
------

- Added factories
- Added spec loaders

v0.4.1
------

Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dirty-loader >= 0.1.0
dirty-loader >= 0.2.0
git+https://github.com/alfred82santa/configure.git
aiohttp
53 changes: 53 additions & 0 deletions service_client/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from logging import Logger
from dirty_loader.factories import BaseFactory, instance_params
from . import ServiceClient
from .plugins import BasePlugin, BaseLogger


class ServiceClientFactory(BaseFactory):

def __call__(self, spec=None, spec_loader=None, plugins=None,
parser=None, serializer=None, logger=None, **kwargs):
if spec_loader:
loader_class, params = instance_params(spec_loader)
loader = self.loader.load_class(loader_class)
spec = loader(**params)

try:
loaded_plugins = []
for plugin in plugins:
if not isinstance(plugin, BasePlugin):
klass, params = instance_params(plugin)
plugin = self.loader.factory(klass, **params)
loaded_plugins.append(plugin)
plugins = loaded_plugins
except TypeError:
pass

if isinstance(parser, str):
parser = self.loader.load_class(parser)

if isinstance(serializer, str):
serializer = self.loader.load_class(serializer)

if logger and not isinstance(logger, Logger):
klass, params = instance_params(logger)
logger = self.loader.factory(klass, **params)

return super(ServiceClientFactory, self).__call__(spec=spec, plugins=plugins, parser=parser,
serializer=serializer, logger=logger, **kwargs)


class LoggerPluginFactory(BaseFactory):

def __call__(self, logger, **kwargs):
if logger and not isinstance(logger, Logger):
klass, params = instance_params(logger)
logger = self.loader.factory(klass, **params)

return super(LoggerPluginFactory, self).__call__(logger=logger, **kwargs)


def register_service_client_factories(loader):
loader.register_factory(ServiceClient, ServiceClientFactory)
loader.register_factory(BaseLogger, LoggerPluginFactory)
24 changes: 24 additions & 0 deletions service_client/spec_loaders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@


def json_loader(filename):
from json import load
with open(filename) as f:
return load(f)


def yaml_loader(filename):
from yaml import load
with open(filename) as f:
return load(f)


def configuration_loader(filename):
from collections import Mapping
from configure import Configuration
config = Configuration.from_file(filename)
config.configure()

def to_dict(mapping):
return {k: (to_dict(v) if isinstance(v, Mapping) else v) for k, v in mapping.items()}

return to_dict(config)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
name='aio-service-client',
url='https://github.com/alfred82santa/aio-service-client',
author='alfred82santa',
version='0.4.1',
version='0.5.0',
license='LGPLv3',
author_email='alfred82santa@gmail.com',
classifiers=[
Expand Down
1 change: 1 addition & 0 deletions tests/specs/spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"endpoint1": {"path": "/ssssss", "method": "get"}}
3 changes: 3 additions & 0 deletions tests/specs/spec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
endpoint1:
path: /ssssss
method: get
4 changes: 4 additions & 0 deletions tests/specs/spec_extends.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--- !extends:spec.yaml
endpoint2:
path: /bbbbbb
method: post
98 changes: 98 additions & 0 deletions tests/tests_factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from logging import getLogger, NullHandler
from unittest.case import TestCase

from dirty_loader import LoaderNamespace
from dirty_loader.factories import register_logging_factories

from service_client import ServiceClient
from service_client.factories import register_service_client_factories
from service_client.json import json_decoder, json_encoder
from service_client.plugins import InnerLogger, PathTokens


class LoggerPluginFactoryFactoryTests(TestCase):

def setUp(self):
self.loader = LoaderNamespace()
self.loader.register_namespace('logging', 'logging')
self.loader.register_namespace('sc-plugins', 'service_client.plugins')
register_logging_factories(self.loader)
register_service_client_factories(self.loader)

def test_inner_logger_build(self):
plugin = self.loader.factory('sc-plugins:InnerLogger', logger={'type': 'logging:Logger',
'params': {'name': 'foo.bar.test.1',
'handlers': ['logging:NullHandler']}})
self.assertIsInstance(plugin, InnerLogger)
self.assertEqual(plugin.logger, getLogger('foo.bar.test.1'))
self.assertEqual(len(plugin.logger.handlers), 1)
self.assertIsInstance(plugin.logger.handlers[0], NullHandler)


def fake_loader(value='foo'):
return {'test': {'path': value}}


class ServiceClientFactoryTests(TestCase):

def setUp(self):
self.loader = LoaderNamespace()
self.loader.register_namespace('logging', 'logging')
self.loader.register_namespace('sc', 'service_client')
self.loader.register_namespace('sc-plugins', 'service_client.plugins')
self.loader.register_namespace('here', __name__)
register_logging_factories(self.loader)
register_service_client_factories(self.loader)

def test_service_client_basic(self):

definition = {'name': 'test1',
'spec': {'test': {'path': 'baz'}},
'parser': 'sc:json.json_decoder',
'serializer': 'sc:json.json_encoder',
'logger': {'type': 'logging:Logger',
'params': {'name': 'foo.bar.test.2',
'handlers': ['logging:NullHandler']}}}

sc = self.loader.factory('sc:ServiceClient', **definition)

self.assertIsInstance(sc, ServiceClient)
self.assertEqual(sc.name, 'test1')
self.assertEqual(sc.spec, definition['spec'])
self.assertEqual(sc.parser, json_decoder)
self.assertEqual(sc.serializer, json_encoder)
self.assertEqual(sc.logger, getLogger('foo.bar.test.2'))
self.assertEqual(len(sc.logger.handlers), 1)
self.assertIsInstance(sc.logger.handlers[0], NullHandler)

def test_service_client_with_plugins(self):
definition = {'name': 'test1',
'spec': {'test': {'path': 'baz'}},
'plugins': ['sc-plugins:PathTokens',
{'type': 'sc-plugins:InnerLogger',
'params': {'logger': {'type': 'logging:Logger',
'params': {'name': 'foo.bar.test.3',
'handlers': ['logging:NullHandler']}}}}]}

sc = self.loader.factory('sc:ServiceClient', **definition)

self.assertIsInstance(sc, ServiceClient)
self.assertEqual(sc.name, 'test1')
self.assertEqual(sc.spec, definition['spec'])
self.assertEqual(len(sc._plugins), 2)
self.assertIsInstance(sc._plugins[0], PathTokens)
self.assertIsInstance(sc._plugins[1], InnerLogger)
self.assertEqual(sc._plugins[1].logger, getLogger('foo.bar.test.3'))
self.assertEqual(len(sc._plugins[1].logger.handlers), 1)
self.assertIsInstance(sc._plugins[1].logger.handlers[0], NullHandler)

def test_service_client_with_spec_loader(self):
definition = {'name': 'test1',
'spec_loader': {'type': 'here:fake_loader',
'params': {'value': 'baz'}}}

sc = self.loader.factory('sc:ServiceClient', **definition)

self.assertIsInstance(sc, ServiceClient)
self.assertEqual(sc.name, 'test1')
self.assertEqual(sc.spec, {'test': {'path': 'baz'}})
31 changes: 31 additions & 0 deletions tests/tests_spec_loaders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
from unittest.case import TestCase
from service_client.spec_loaders import json_loader, yaml_loader, configuration_loader

SPECS_DIR = os.path.join(os.path.dirname(__file__), 'specs')


class JsonLoaderTests(TestCase):

def test_load_spec(self):
spec = json_loader(os.path.join(SPECS_DIR, 'spec.json'))
self.assertEqual(spec, {"endpoint1": {"path": "/ssssss",
"method": "get"}})


class YamlLoaderTests(TestCase):

def test_load_spec(self):
spec = yaml_loader(os.path.join(SPECS_DIR, 'spec.yaml'))
self.assertEqual(spec, {"endpoint1": {"path": "/ssssss",
"method": "get"}})


class ConfigurationLoaderTests(TestCase):

def test_load_spec(self):
spec = configuration_loader(os.path.join(SPECS_DIR, 'spec_extends.yaml'))
self.assertEqual(spec, {"endpoint1": {"path": "/ssssss",
"method": "get"},
"endpoint2": {"path": "/bbbbbb",
"method": "post"}})

0 comments on commit b232382

Please sign in to comment.