import json
import jsonschema
import requests
-from requests.utils import urlparse, urlunparse
import types
-from urlparse import urljoin
+from urlparse import urljoin, urlparse, urlunparse
LOGGER = logging.getLogger(__name__)
# provide common defaults.
None: {
# terms in multiple encoded objects
+ 'award': { '@type': '@id' },
+ 'dataset': {'@type': '@id'},
'description': 'rdf:description',
+ 'documents': { '@type': '@id' },
'experiment': {'@type': '@id'},
'href': { '@type': '@id' },
'lab': { '@type': '@id' },
'library': {'@type': '@id' },
'pi': { '@type': '@id' },
'platform': { '@type': '@id' },
+ 'replicates': { '@type': '@id' },
'submitted_by': { '@type': '@id' },
'url': { '@type': '@id' },
},
},
'experiment': {
"assay_term_id": { "@type": "@id" },
- },
- 'file': {
- 'dataset': {'@type': '@id'},
+ "files": { "@type": "@id" },
+ "original_files": { "@type": "@id"},
},
# I tried to use the JSON-LD mapping capabilities to convert the lab
# contact information into a vcard record, but the encoded model
# "state": "vcard:region",
# "country": "vcard:country"
#},
- 'human_donor': {
- 'award': { '@type': '@id' },
- },
'library': {
- 'award': { '@type': '@id' },
'nucleic_acid_term_id': { '@type': '@id' }
}
}
# OBI: available from http://svn.code.sf.net/p/obi/code/releases/2012-07-01/merged/merged-obi-comments.owl
'SO': 'http://purl.obolibrary.org/obo/SO_', # Sequence ontology
# SO: available from http://www.berkeleybop.org/ontologies/so.owl
+ # NTR: New Term Request space for DCC to implement new ontology terms
}
self.username = None
self.password = None
self.contexts = contexts if contexts else ENCODED_CONTEXT
+ self.json_headers = {'Content-Type': 'application/json'}
self.schemas = {}
def get_auth(self):
self.username = authenticators[0]
self.password = authenticators[2]
- def add_jsonld_context(self, tree, contexts, base):
+ def add_jsonld_context(self, tree, default_base):
"""Add contexts to various objects in the tree.
tree is a json tree returned from the DCC's encoded database.
base, if supplied allows setting the base url that relative
urls will be resolved against.
"""
- tree['@context'] = contexts[None]
- tree['@context']['@base'] = base
- self.add_jsonld_child_context(tree, contexts)
+ self.add_jsonld_child_context(tree, default_base)
+ self.add_jsonld_namespaces(tree['@context'])
- def add_jsonld_child_context(self, obj, contexts):
+ def add_jsonld_child_context(self, obj, default_base):
'''Add JSON-LD context to the encoded JSON.
This is recursive because some of the IDs were relative URLs
LOGGER.info('requesting url: {}'.format(url))
# do the request
- headers = {'content-type': 'application/json'}
+
LOGGER.debug('username: %s, password: %s', self.username, self.password)
- response = requests.get(url, auth=self.auth, headers=headers, params=kwargs)
+ response = requests.get(url, auth=self.auth, headers=self.json_headers, params=kwargs)
if not response.status_code == requests.codes.ok:
LOGGER.error("Error http status: {}".format(response.status_code))
response.raise_for_status()
'''
url = self.prepare_url(obj_id)
json = self.get_json(obj_id, **kwargs)
- self.add_jsonld_context(json, self.context, url)
+ self.add_jsonld_context(json, url)
return json
def get_object_type(self, obj):
def get_schema_url(self, obj):
obj_type = self.get_object_type(obj)
if obj_type:
- return self.prepare_url(ENCODED_SCHEMA_ROOT + obj_type + '.json')
+ return self.prepare_url(ENCODED_SCHEMA_ROOT + obj_type + '.json') + '#'
def _is_encoded_object(self, obj):
'''Test to see if an object is a JSON-LD object
"""
url = self.prepare_url(obj_id)
payload = json.dumps(changes)
- response = requests.patch(url, auth=self.auth, data=payload)
+ response = requests.patch(url, auth=self.auth, headers=self.json_headers, data=payload)
if response.status_code != requests.codes.ok:
LOGGER.error("Error http status: {}".format(response.status_code))
+ LOGGER.error("Response: %s", response.text)
response.raise_for_status()
return response.json()
def put_json(self, obj_id, new_object):
url = self.prepare_url(obj_id)
payload = json.dumps(new_object)
- response = requests.put(url, auth=self.auth, data=payload)
+ response = requests.put(url, auth=self.auth, headers=self.json_headers, data=payload)
+ if response.status_code != requests.codes.created:
+ LOGGER.error("Error http status: {}".format(response.status_code))
+ response.raise_for_status()
+ return response.json()
+
+ def post_json(self, collection_id, new_object):
+ url = self.prepare_url(collection_id)
+ payload = json.dumps(new_object)
+ response = requests.post(url, auth=self.auth, headers=self.json_headers, data=payload)
if response.status_code != requests.codes.created:
LOGGER.error("Error http status: {}".format(response.status_code))
response.raise_for_status()
# clean up potentially messy urls
url = urlparse(request_url)._asdict()
if not url['scheme']:
- url['scheme'] = 'http'
+ url['scheme'] = 'https'
if not url['netloc']:
url['netloc'] = self.server
url = urlunparse(url.values())
return url
+ def search_jsonld(self, term, **kwargs):
+ '''Send search request to ENCODED
+ '''
+ url = self.prepare_url('/search/')
+ result = self.get_json(url, searchTerm=term, **kwargs)
+ self.convert_search_to_jsonld(result)
+ return result
+
+ def convert_search_to_jsonld(self, result):
+ '''Add the context to search result
+
+ Also remove hard to handle nested attributes
+ e.g. remove object.term when we have no id
+ '''
+ graph = result['@graph']
+ for i, obj in enumerate(graph):
+ # suppress nested attributes
+ graph[i] = {k: v for k, v in obj.items() if '.' not in k}
+
+ self.add_jsonld_context(result, self.prepare_url(result['@id']))
+ return result
+
def validate(self, obj):
obj_type = self.get_object_type(obj)
schema_url = self.get_schema_url(obj)