<s> from coreapi . codecs . base import BaseCodec , _get_string , _get_list , _get_dict , get_dicts <EOL> from coreapi . compat import urlparse <EOL> from coreapi . document import Document , Link , Field <EOL> from coreapi . exceptions import ParseError <EOL> import json <EOL> import uritemplate <EOL> import urllib <EOL> def _dereference ( value , ref ) : <EOL> keys = value . strip ( '<STR_LIT>' ) . split ( '<STR_LIT:/>' ) <EOL> node = ref <EOL> for key in keys : <EOL> node = _get_dict ( node , key ) <EOL> return node <EOL> def _get_content ( data , base_url , ref ) : <EOL> content = { } <EOL> links = _get_list ( data , '<STR_LIT>' ) <EOL> properties = _get_dict ( data , '<STR_LIT>' ) <EOL> if properties : <EOL> for key , value in properties . items ( ) : <EOL> if not isinstance ( value , dict ) : <EOL> continue <EOL> if list ( value . keys ( ) ) == [ '<STR_LIT>' ] : <EOL> value = _dereference ( value [ '<STR_LIT>' ] , ref ) <EOL> sub_content = _get_content ( value , base_url , ref ) <EOL> if sub_content : <EOL> content [ key ] = sub_content <EOL> if links : <EOL> for link in get_dicts ( links ) : <EOL> rel = _get_string ( link , '<STR_LIT>' ) <EOL> if rel : <EOL> href = _get_string ( link , '<STR_LIT>' ) <EOL> method = _get_string ( link , '<STR_LIT>' ) <EOL> schema = _get_dict ( link , '<STR_LIT>' ) <EOL> schema_type = _get_list ( schema , '<STR_LIT:type>' ) <EOL> schema_properties = _get_dict ( schema , '<STR_LIT>' ) <EOL> schema_required = _get_list ( schema , '<STR_LIT>' ) <EOL> fields = [ ] <EOL> url = urlparse . urljoin ( base_url , href ) <EOL> templated = uritemplate . variables ( url ) <EOL> for item in templated : <EOL> orig = item <EOL> if item . startswith ( '<STR_LIT:(>' ) and item . endswith ( '<STR_LIT:)>' ) : <EOL> item = urllib . unquote ( item . strip ( '<STR_LIT:(>' ) . rstrip ( '<STR_LIT:)>' ) ) <EOL> if item . startswith ( '<STR_LIT>' ) : <EOL> components = [ <EOL> component for component in item . strip ( '<STR_LIT>' ) . split ( '<STR_LIT:/>' ) <EOL> if component != '<STR_LIT>' <EOL> ] <EOL> item = '<STR_LIT:_>' . join ( components ) . replace ( '<STR_LIT:->' , '<STR_LIT:_>' ) <EOL> url = url . replace ( orig , item ) <EOL> fields . append ( Field ( name = item , location = '<STR_LIT:path>' , required = True ) ) <EOL> if schema_type == [ '<STR_LIT:object>' ] and schema_properties : <EOL> fields += [ <EOL> Field ( name = key , required = ( key in schema_required ) ) <EOL> for key in schema_properties . keys ( ) <EOL> ] <EOL> if rel == '<STR_LIT>' : <EOL> rel = '<STR_LIT>' <EOL> content [ rel ] = Link ( url = url , action = method , fields = fields ) <EOL> return content <EOL> def _primative_to_document ( data , base_url ) : <EOL> url = base_url <EOL> links = _get_list ( data , '<STR_LIT>' ) <EOL> for link in get_dicts ( links ) : <EOL> href = _get_string ( link , '<STR_LIT>' ) <EOL> rel = _get_string ( link , '<STR_LIT>' ) <EOL> if rel == '<STR_LIT>' and href : <EOL> url = urlparse . urljoin ( url , href ) <EOL> title = _get_string ( data , '<STR_LIT:title>' ) <EOL> content = _get_content ( data , url , ref = data ) <EOL> return Document ( title = title , url = url , content = content ) <EOL> class HyperschemaCodec ( BaseCodec ) : <EOL> """<STR_LIT>""" <EOL> media_type = '<STR_LIT>' <EOL> def load ( self , bytes , base_url = None ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> data = json . loads ( bytes . decode ( '<STR_LIT:utf-8>' ) ) <EOL> except ValueError as exc : <EOL> raise ParseError ( '<STR_LIT>' % exc ) <EOL> doc = _primative_to_document ( data , base_url ) <EOL> if not ( isinstance ( doc , Document ) ) : <EOL> raise ParseError ( '<STR_LIT>' ) <EOL> return doc </s>
