Add functions to create a json-ld context and add namespaces to a context
authorDiane Trout <diane@ghic.org>
Fri, 17 Jan 2014 00:06:50 +0000 (16:06 -0800)
committerDiane Trout <diane@ghic.org>
Fri, 17 Jan 2014 00:06:50 +0000 (16:06 -0800)
Having smaller functions like this makes it easier to test.

htsworkflow/submission/encoded.py
htsworkflow/submission/test/test_encoded.py

index 8eec0c0ef60cd44e0123cfc8b7d28d1f8625c50d..507271355988db469a83cb34560c8fb15cabaf93 100644 (file)
@@ -64,7 +64,7 @@ ENCODED_CONTEXT = {
 }
 
 #FIXME: this needs to be initialized from rdfns
-_encoded_namespaces = {
+ENCODED_NAMESPACES = {
     # JSON-LD lets you define namespaces so you can used the shorted url syntax.
     # (instead of http://www.w3.org/2000/01/rdf-schema#label you can do
     # rdfs:label)
@@ -84,17 +84,17 @@ _encoded_namespaces = {
     # SO: available from http://www.berkeleybop.org/ontologies/so.owl
 
 }
-ENCODED_CONTEXT[None].update(_encoded_namespaces)
+
 ENCODED_SCHEMA_ROOT='/profiles/'
 
 class ENCODED:
     '''Programatic access encoded, the software powering ENCODE3's submit site.
     '''
-    def __init__(self, server, context=None):
+    def __init__(self, server, contexts=None):
         self.server = server
         self.username = None
         self.password = None
-        self.context = context if context else ENCODED_CONTEXT
+        self.contexts = contexts if contexts else ENCODED_CONTEXT
         self.schemas = {}
 
     def get_auth(self):
@@ -136,24 +136,41 @@ class ENCODED:
         if isinstance(obj, collections.Sequence):
             # how should I update lists?
             for v in obj:
-                self.add_jsonld_child_context(v, contexts)
+                self.add_jsonld_child_context(v, default_base)
             return
 
         if isinstance(obj, collections.Mapping):
             for v in obj.values():
-                self.add_jsonld_child_context(v, contexts)
+                self.add_jsonld_child_context(v, default_base)
 
         # we have an object. attach a context to it.
         if self._is_encoded_object(obj):
-            default_base = contexts[None]['@base']
-            context = {'@base': urljoin(default_base, obj['@id']),
-                       '@vocab': self.get_schema_url(obj)}
-            for t in obj['@type']:
-                if t in contexts:
-                    context.update(contexts[t])
+            context = self.create_jsonld_context(obj, default_base)
             if len(context) > 0:
                 obj.setdefault('@context', {}).update(context)
 
+    def add_jsonld_namespaces(self, context):
+        '''Add shortcut namespaces to a context
+
+        Only needs to be run on the top-most context
+        '''
+        context.update(ENCODED_NAMESPACES)
+
+    def create_jsonld_context(self, obj, default_base):
+        '''Synthesize the context for a encoded type
+
+        self.contexts[None] = default context attributes added to any type
+        self.contexts[type] = context attributes for this type.
+        '''
+        context = {'@base': urljoin(default_base, obj['@id']),
+                    '@vocab': self.get_schema_url(obj)}
+        # add in defaults
+        context.update(self.contexts[None])
+        for t in obj['@type']:
+            if t in self.contexts:
+                context.update(self.contexts[t])
+        return context
+
     def get_json(self, obj_id, **kwargs):
         '''GET an ENCODE object as JSON and return as dict
 
index e5b270795fcb1338746fd0647936051c657d9ab7..5e0e69b961f9aa8a82ad1563f1c4780f233b60f6 100644 (file)
@@ -3,7 +3,10 @@ import os
 from pprint import pprint
 from unittest2 import TestCase, TestSuite, defaultTestLoader, skip
 
-from htsworkflow.submission.encoded import ENCODED
+from htsworkflow.submission.encoded import (ENCODED,
+     ENCODED_CONTEXT,
+     ENCODED_NAMESPACES
+)
 
 class TestEncoded(TestCase):
     def test_prepare_url(self):
@@ -56,6 +59,20 @@ class TestEncoded(TestCase):
         encode.validate(obj)
         self.assertTrue('@id' in obj)
 
+    def test_create_context(self):
+        linked_id = {'@type': '@id'}
+        library = { '@id': '/libraries/1234', '@type': ['library', 'item'] }
+
+        encode = ENCODED('test.encodedcc.org')
+        url = encode.prepare_url(library['@id'])
+        context = encode.create_jsonld_context(library, url)
+        self.assertEqual(context['award'], linked_id )
+        self._verify_context(context, 'library')
+        # namespaces not added yet.
+        self.assertRaises(AssertionError, self._verify_namespaces, context)
+        encode.add_jsonld_namespaces(context)
+        self._verify_namespaces(context)
+
     def test_add_context(self):
         """Checking to make sure nested @base and @vocab urls are set correctly
         """
@@ -97,7 +114,23 @@ class TestEncoded(TestCase):
 
         self.assertEqual(obj['biosample']['@context']['@base'], bio_base)
         self.assertEqual(obj['@context']['@vocab'], schema_url)
+        self._verify_context(obj['@context'], 'library')
+        self._verify_namespaces(obj['@context'])
+        self._verify_context(obj['biosample']['@context'], 'biosample')
+        self.assertEqual(obj['@context']['rdf'], 'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
+        self.assertEqual(obj['@context']['OBO'], 'http://purl.obolibrary.org/obo/')
+
+
+    def _verify_context(self, context, obj_type):
+        for context_key in [None, obj_type]:
+            for k in ENCODED_CONTEXT[context_key]:
+                self.assertIn(k, context)
+                self.assertEqual(ENCODED_CONTEXT[context_key][k], context[k])
 
+    def _verify_namespaces(self, context):
+        for k in ENCODED_NAMESPACES:
+            self.assertIn(k, context)
+            self.assertEqual(ENCODED_NAMESPACES[k], context[k])
 
 def suite():
     suite = TestSuite()