This repository has been archived by the owner on Mar 18, 2019. It is now read-only.
/
__init__.py
110 lines (92 loc) · 3.72 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# coding: utf-8
from coreapi.codecs.base import BaseCodec
from coreapi.compat import urlparse
from coreapi.document import Document, Link, Field
from coreapi.exceptions import ParseError
from jsonhyperschema_codec.utils import _get_string, _get_list, _get_dict, get_dicts, _dereference
import json
import uritemplate
try:
from urllib.parse import unquote
except ImportError:
from urllib import unquote
__version__ = "1.0.3"
def _get_content(data, base_url, ref):
content = {}
links = _get_list(data, 'links')
properties = _get_dict(data, 'properties')
if properties:
for key, value in properties.items():
if not isinstance(value, dict):
continue
if list(value.keys()) == ['$ref']:
value = _dereference(value['$ref'], ref)
sub_content = _get_content(value, base_url, ref)
if sub_content:
content[key] = sub_content
if links:
for link in get_dicts(links):
rel = _get_string(link, 'rel')
if rel:
href = _get_string(link, 'href')
method = _get_string(link, 'method')
schema = _get_dict(link, 'schema')
schema_type = _get_list(schema, 'type')
schema_properties = _get_dict(schema, 'properties')
schema_required = _get_list(schema, 'required')
fields = []
url = urlparse.urljoin(base_url, href)
templated = uritemplate.variables(url)
for item in templated:
orig = item
if item.startswith('(') and item.endswith(')'):
item = unquote(item.strip('(').rstrip(')'))
if item.startswith('#/'):
components = [
component for component in item.strip('#/').split('/')
if component != 'definitions'
]
item = '_'.join(components).replace('-', '_')
url = url.replace(orig, item)
fields.append(Field(name=item, location='path', required=True))
if schema_type == ['object'] and schema_properties:
fields += [
Field(name=key, required=(key in schema_required))
for key in schema_properties.keys()
]
if rel == 'self':
rel = 'read'
content[rel] = Link(url=url, action=method, fields=fields)
return content
def _primative_to_document(data, base_url):
url = base_url
# Determine if the document contains a self URL.
links = _get_list(data, 'links')
for link in get_dicts(links):
href = _get_string(link, 'href')
rel = _get_string(link, 'rel')
if rel == 'self' and href:
url = urlparse.urljoin(url, href)
# Load the document content.
title = _get_string(data, 'title')
content = _get_content(data, url, ref=data)
return Document(title=title, url=url, content=content)
class JSONHyperSchemaCodec(BaseCodec):
"""
JSON Hyper-Schema.
"""
media_type = 'application/schema+json'
supports = ['decoding']
def load(self, bytes, **kwargs):
"""
Takes a bytestring and returns a document.
"""
base_url = kwargs.get('base_url', None)
try:
data = json.loads(bytes.decode('utf-8'))
except ValueError as exc:
raise ParseError('Malformed JSON. %s' % exc)
doc = _primative_to_document(data, base_url)
if not (isinstance(doc, Document)):
raise ParseError('Top level node must be a document.')
return doc