Skip to content

Commit

Permalink
utils: add option to load resolved schemas
Browse files Browse the repository at this point in the history
Signed-off-by: Glignos <glignos93@gmail.com>
  • Loading branch information
Glignos authored and michamos committed Nov 13, 2017
1 parent 83b667f commit cdbac40
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 13 deletions.
39 changes: 28 additions & 11 deletions inspire_schemas/utils.py
Expand Up @@ -43,6 +43,7 @@
from .errors import SchemaKeyNotFound, SchemaNotFound

_schema_root_path = os.path.abspath(resource_filename(__name__, 'records'))
_resolved_schema_root_path = os.path.abspath(resource_filename(__name__, 'resolved_records'))

_RE_2_CHARS = re.compile(r'[a-z].*[a-z]', re.IGNORECASE)
_RE_CHAR = re.compile(r'[a-z]', re.IGNORECASE)
Expand Down Expand Up @@ -431,15 +432,22 @@ def resolve_remote(self, uri):
)


def get_schema_path(schema):
def get_schema_path(schema, resolved=False):
"""Retrieve the installed path for the given schema.
:param schema: String with the (relative or absolute) url of the
schema to validate, for example, 'records/authors.json' or 'jobs.json',
or by just the name like 'jobs'.
:type schema: str
:return: The path or the given schema name.
:rtype: str
Args:
schema(str): relative or absolute url of the schema to validate, for
example, 'records/authors.json' or 'jobs.json', or just the name of the
schema, like 'jobs'.
resolved(bool): if True, the returned path points to a fully resolved
schema, that is to the schema with all `$ref`s replaced by their
targets.
Returns:
str: path to the given schema name.
Raises:
SchemaNotFound: if no schema could be found.
"""
def _strip_first_path_elem(path):
"""Pass doctests.
Expand Down Expand Up @@ -468,7 +476,10 @@ def _schema_to_normalized_path(schema):

path = _schema_to_normalized_path(schema)
while path:
schema_path = os.path.abspath(os.path.join(_schema_root_path, path))
if resolved:
schema_path = os.path.abspath(os.path.join(_resolved_schema_root_path, path))
else:
schema_path = os.path.abspath(os.path.join(_schema_root_path, path))
if os.path.exists(schema_path):
return os.path.abspath(schema_path)

Expand All @@ -477,13 +488,19 @@ def _schema_to_normalized_path(schema):
raise SchemaNotFound(schema=schema)


def load_schema(schema_name):
def load_schema(schema_name, resolved=False):
"""Load the given schema from wherever it's installed.
:param schema_name: Name of the schema to load, for example 'authors'.
Args:
schema_name(str): Name of the schema to load, for example 'authors'.
resolved(bool): If True will return the resolved schema, that is with
all the $refs replaced by their targets.
Returns:
dict: the schema with the given name.
"""
schema_data = ''
with open(get_schema_path(schema_name)) as schema_fd:
with open(get_schema_path(schema_name, resolved)) as schema_fd:
schema_data = json.loads(schema_fd.read())

if '$schema' not in schema_data:
Expand Down
12 changes: 10 additions & 2 deletions tests/unit/test_utils.py
Expand Up @@ -140,6 +140,14 @@ def test_get_schema_path_positive(schema, expected):
assert schema_path == os.path.join(utils._schema_root_path, expected)


@mock.patch('os.path.exists')
def test_get_resolved_schema_path(mock_exists):
schema_path = utils.get_schema_path(schema='hep.json', resolved=True)
mock_exists.side_effect = \
lambda x: x == os.path.join(utils._resolved_schema_root_path, 'hep.json')
assert schema_path == os.path.join(utils._resolved_schema_root_path, 'hep.json')


@pytest.mark.parametrize(
'schema',
(
Expand Down Expand Up @@ -214,7 +222,7 @@ def test_load_schema_with_schema_key(mock_get_schema_path, mock_open):
mock_open.side_effect = \
lambda x: contextlib.closing(six.StringIO(json.dumps(myschema)))
mock_get_schema_path.side_effect = \
lambda x: 'And his nostrils ripped and his bottom burned off'
lambda x, y: 'And his nostrils ripped and his bottom burned off'

loaded_schema = utils.load_schema('And gallantly he chickened out')

Expand All @@ -230,7 +238,7 @@ def test_load_schema_without_schema_key(mock_get_schema_path, mock_open):
mock_open.side_effect = \
lambda x: contextlib.closing(six.StringIO(json.dumps(myschema)))
mock_get_schema_path.side_effect = \
lambda x: 'And his nostrils ripped and his bottom burned off'
lambda x, y: 'And his nostrils ripped and his bottom burned off'

loaded_schema = utils.load_schema('And gallantly he chickened out')

Expand Down

0 comments on commit cdbac40

Please sign in to comment.