Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ charset = utf-8
indent_size = 4
# isort plugin configuration
known_first_party = jsonresolver
known_third_party = werkzeug
multi_line_output = 2
default_section = THIRDPARTY

Expand Down
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ Authors
JSON data resolver with support for plugins.

- Jiri Kuncar <jiri.kuncar@cern.ch>
- Krzysztof Nowak <k.nowak@cern.ch>
5 changes: 3 additions & 2 deletions jsonresolver/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ def __init__(self, plugins=None, entry_point_group=None):
)
if entry_point_group:
self.pm.load_setuptools_entrypoints(entry_point_group)

self._build_url_map()
self.url_map = None

def _build_url_map(self):
"""Build an URL map from registered plugins."""
Expand All @@ -43,6 +42,8 @@ def _build_url_map(self):

def resolve(self, url):
"""Resolve given URL and use regitered loader."""
if self.url_map is None:
self._build_url_map()
parts = urlsplit(url)
loader, args = self.url_map.bind(parts.hostname).match(parts.path)
return loader(**args)
6 changes: 3 additions & 3 deletions jsonresolver/hookspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# This file is part of jsonresolver
# Copyright (C) 2015 CERN.
#
# jsonresolver is free software; you can redistribute it and/or modify
# it under the terms of the Revised BSD License; see LICENSE file for
# more details.
# jsonresolver is free software; you can redistribute it and/or
# modify it under the terms of the Revised BSD License; see LICENSE
# file for more details.

"""Define hook specification."""

Expand Down
2 changes: 1 addition & 1 deletion run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@


pep257 jsonresolver && \
# FIXME isort -rc -c -df **/*.py && \
isort -rc -c -df **/*.py && \
check-manifest --ignore ".travis-*" && \
sphinx-build -qnNW docs docs/_build/html && \
python setup.py test && \
Expand Down
16 changes: 14 additions & 2 deletions tests/demo/internals.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import jsonresolver
import requests
# -*- coding: utf-8 -*-
#
# This file is part of jsonresolver
# Copyright (C) 2015 CERN.
#
# jsonresolver is free software; you can redistribute it and/or
# modify it under the terms of the Revised BSD License; see LICENSE
# file for more details.

"""Test adding JSON resolving rule using ``werkzeug.routing.Rule`` object."""

import requests
from werkzeug.routing import Rule

import jsonresolver


@jsonresolver.hookimpl
def jsonresolver_loader(url_map):
"""Load the resolver plugin as a Rule to URL map."""
def endpoint(recid):
return requests.get(
'https://cds.cern.ch/record/{recid}?of=recjson'.format(recid=recid)
Expand Down
22 changes: 22 additions & 0 deletions tests/demo/raising.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#
# This file is part of jsonresolver
# Copyright (C) 2015 CERN.
#
# jsonresolver is free software; you can redistribute it and/or
# modify it under the terms of the Revised BSD License; see LICENSE
# file for more details.

"""Test for detecting the lazy evaluation of decorated JSON resolver."""

import jsonresolver


class EndpointCallDetected(Exception):
"""Raise this ``exception`` to detect when a plugin is called in test."""


@jsonresolver.route('/test', host='http://localhost:4000')
def raising():
"""Raise an exception."""
raise EndpointCallDetected
22 changes: 22 additions & 0 deletions tests/demo/raising_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#
# This file is part of jsonresolver
# Copyright (C) 2015 CERN.
#
# jsonresolver is free software; you can redistribute it and/or
# modify it under the terms of the Revised BSD License; see LICENSE
# file for more details.

"""Test for detecting the lazy evaluation of hook-registered JSON resolver."""

import jsonresolver


class HookRegistrationDetected(Exception):
"""Raise this ``exception`` to detect when a hook is registered."""


@jsonresolver.hookimpl
def jsonresolver_loader(url_map):
"""Load the raising plugin as a Rule to URL map."""
raise HookRegistrationDetected
3 changes: 3 additions & 0 deletions tests/demo/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
# modify it under the terms of the Revised BSD License; see LICENSE
# file for more details.

"""Test plugin for JSON schema resolving using decorator."""

import jsonresolver


@jsonresolver.route('/schema/<path:name>', host='http://localhost:4000')
def schema(name):
"""Return a fixed JSON ``schema``."""
assert name == 'authors.json'
return {'type': 'array'}
3 changes: 3 additions & 0 deletions tests/demo/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
# modify it under the terms of the Revised BSD License; see LICENSE
# file for more details.

"""Test plugin for JSON resolving using ``jsonresolver.route`` decorator."""

import jsonresolver


@jsonresolver.route('/test', host='http://localhost:4000')
def simple():
"""Return a fixed JSON."""
return {'test': 'test'}
43 changes: 43 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,32 @@
import importlib

import pytest
from demo.raising import EndpointCallDetected
from demo.raising_hook import HookRegistrationDetected
from mock import patch
from pkg_resources import EntryPoint

from jsonresolver import JSONResolver


class MockEntryPoint(EntryPoint):
"""EntryPoint mock."""

def load(self):
"""Load module from the mocked entry point."""
if self.name == 'importfail':
raise ImportError()
else:
return importlib.import_module(self.name)


def _mock_entry_points(name):
"""Mock the entry points."""
data = {
'espresso': [MockEntryPoint('demo.simple', 'demo.simple')],
'raising': [MockEntryPoint('demo.raising', 'demo.raising')],
'raising_hook': [MockEntryPoint('demo.raising_hook',
'demo.raising_hook')],
'someotherstuff': [],
'doubletrouble': [MockEntryPoint('demo.simple', 'demo.simple'),
MockEntryPoint('demo.simple', 'demo.simple')],
Expand All @@ -45,10 +54,44 @@ def _mock_entry_points(name):

@patch('pkg_resources.iter_entry_points', _mock_entry_points)
def test_entry_point_group():
"""Test the entry point group loading."""
resolver = JSONResolver(entry_point_group='espresso')
assert resolver.resolve('http://localhost:4000/test') == {'test': 'test'}


def test_plugins():
"""Test the plugins loading."""
resolver = JSONResolver(plugins=['demo.simple'])
assert resolver.resolve('http://localhost:4000/test') == {'test': 'test'}


@patch('pkg_resources.iter_entry_points', _mock_entry_points)
def test_plugin_lazy_execution():
"""Test the lazy evaluation of loaded plugin."""
# Plugin code should be called (i.e. raise exception) on resolve method
resolver = JSONResolver(plugins=['demo.raising'])
with pytest.raises(EndpointCallDetected) as exc_info:
resolver.resolve('http://localhost:4000/test')
assert exc_info.type is EndpointCallDetected

# Same as above but loaded using entry point
resolver = JSONResolver(entry_point_group='raising')
with pytest.raises(EndpointCallDetected) as exc_info:
resolver.resolve('http://localhost:4000/test')
assert exc_info.type is EndpointCallDetected


@patch('pkg_resources.iter_entry_points', _mock_entry_points)
def test_plugin_lazy_execution_hooks():
"""Test the lazy evaluation of loaded plugin through hooks."""
# Plugin code should be called (i.e. raise exception) on resolve method
resolver = JSONResolver(plugins=['demo.raising_hook'])
with pytest.raises(HookRegistrationDetected) as exc_info:
resolver.resolve('http://localhost:4000/test')
assert exc_info.type is HookRegistrationDetected

# Same as above but loaded using entry point
resolver = JSONResolver(entry_point_group='raising_hook')
with pytest.raises(HookRegistrationDetected) as exc_info:
resolver.resolve('http://localhost:4000/test')
assert exc_info.type is HookRegistrationDetected
2 changes: 1 addition & 1 deletion tests/test_jsonref.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

from __future__ import absolute_import

from jsonref import JsonRef, JsonRefError
import pytest
from jsonref import JsonRef, JsonRefError

from jsonresolver import JSONResolver
from jsonresolver.contrib.jsonref import json_loader_factory
Expand Down
2 changes: 1 addition & 1 deletion tests/test_jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

from __future__ import absolute_import

from jsonschema import RefResolutionError, validate
import pytest
from jsonschema import RefResolutionError, validate

from jsonresolver import JSONResolver
from jsonresolver.contrib.jsonschema import ref_resolver_factory
Expand Down