[Python-modules-commits] [python-pyld] 122/276: Update fromRDF to comply with recent changes to the spec.

Wolfgang Borgert debacle at moszumanska.debian.org
Wed Oct 8 23:48:00 UTC 2014


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to branch master
in repository python-pyld.

commit d7dcc29a81fb265f48261f7c9b6feaf1689ddd71
Author: Dave Longley <dlongley at digitalbazaar.com>
Date:   Fri May 17 16:26:04 2013 -0400

    Update fromRDF to comply with recent changes to the spec.
---
 lib/pyld/jsonld.py | 185 +++++++++++++++++++++++++++--------------------------
 1 file changed, 95 insertions(+), 90 deletions(-)

diff --git a/lib/pyld/jsonld.py b/lib/pyld/jsonld.py
index c4d6df1..f2007c3 100644
--- a/lib/pyld/jsonld.py
+++ b/lib/pyld/jsonld.py
@@ -1951,103 +1951,112 @@ class JsonLdProcessor:
         
         :return: the JSON-LD output.
         """
-        # prepare graph map (maps graph name => subjects, lists)
-        default_graph = {'subjects': {}, 'listMap': {}}
-        graphs = {'@default': default_graph}
-
-        for graph_name, triples in dataset.items():
-            for triple in triples:
+        default_graph = {}
+        graph_map = {'@default': default_graph}
+
+        for name, graph in dataset.items():
+            graph_map.setdefault(name, {})
+            if name != '@default' and name not in default_graph:
+                default_graph[name] = {'@id': name}
+            node_map = graph_map[name]
+            for triple in graph:
                 # get subject, predicate, object
                 s = triple['subject']['value']
                 p = triple['predicate']['value']
                 o = triple['object']
 
-                # create a named graph entry as needed
-                graph = graphs.setdefault(
-                    graph_name, {'subjects': {}, 'listMap': {}})
-
-                # handle element in @list
-                if p == RDF_FIRST:
-                    # create list entry as needed
-                    list_map = graph['listMap']
-                    entry = list_map.setdefault(s, {})
-                    # set object value
-                    entry['first'] = self._rdf_to_object(
-                        o, options['useNativeTypes'])
+                node = node_map.setdefault(s, {'@id': s})
+
+                object_is_id = (o['type'] == 'IRI' or o['type'] == 'blank node')
+                if (object_is_id and o['value'] != RDF_NIL and
+                    o['value'] not in node_map):
+                    node_map[o['value']] = {'@id': o['value']}
+
+                if p == RDF_TYPE and object_is_id:
+                    JsonLdProcessor.add_value(
+                        node, '@type', o['value'], {'propertyIsArray': True})
                     continue
 
-                # handle other element in @list
-                if p == RDF_REST:
-                    # set next in list
-                    if o['type'] == 'blank node':
-                        # create list entry as needed
-                        list_map = graph['listMap']
-                        entry = list_map.setdefault(s, {})
-                        entry['rest'] = o['value']
+                if object_is_id and o['value'] == RDF_NIL and p != RDF_REST:
+                    # empty list detected
+                    value = {'@list': []}
+                else:
+                    value = self._rdf_to_object(o, options['useNativeTypes'])
+                JsonLdProcessor.add_value(
+                    node, p, value, {'propertyIsArray': True})
+
+                # object may be the head of an RDF list but we can't know
+                # easily until all triples are read
+                if o['type'] == 'blank node' and p not in [RDF_FIRST, RDF_REST]:
+                    object = node_map[o['value']]
+                    if 'listHeadFor' not in object:
+                        object['listHeadFor'] = value
+                    # can't be a list head if referenced more than once
+                    else:
+                        object['listHeadFor'] = None
+
+        # convert linked lists to @list arrays
+        for name, graph_object in graph_map.items():
+            for subject, node in sorted(graph_object.items()):
+                # if subject not in graph_object, it has been removed as it
+                # was part of an RDF list, continue
+                if subject not in graph_object:
+                    continue
+                # if value is not an object, it can't be a list head, continue
+                value = node.get('listHeadFor')
+                if not _is_object(value):
                     continue
 
-                # add graph subject to the default graph as needed
-                if (graph_name != '@default' and
-                    graph_name not in default_graph['subjects']):
-                    default_graph['subjects'].setdefault(
-                        graph_name, {'@id': graph_name})
+                list = []
+                eliminated_nodes = set()
+                while subject != RDF_NIL and list != None:
+                    # ensure node is a valid list node; node must:
+                    # 1. Be a blank node.
+                    # 2. Have no keys other than:
+                    #   @id, listHeadFor, rdf:first, rdf:rest
+                    # 3. Have an array for rdf:first that has 1 item
+                    # 4. Have an array for rdf:rest that has 1 object w/@id.
+                    # 5. Not already be in a list (it is in eliminated_nodes)
+                    node = node or {}
+                    node_key_count = len(node.keys())
+                    rdf_first = node.get(RDF_FIRST)
+                    rdf_rest = node.get(RDF_REST)
+                    if not (_is_object(node) and
+                        node['@id'].startswith('_:') and
+                        (node_key_count == 3 or
+                         node_key_count == 4 and 'listHeadFor' in node) and
+                        _is_array(rdf_first) and len(rdf_first) == 1 and
+                        _is_array(rdf_rest) and len(rdf_rest) == 1 and
+                        _is_object(rdf_rest[0]) and '@id' in rdf_rest[0] and
+                        subject not in eliminated_nodes):
+                        list = None
+                        break
 
-                # add subject to graph as needed
-                subjects = graph['subjects']
-                value = subjects.setdefault(s, {'@id': s})
+                    list.append(rdf_first[0])
+                    eliminated_nodes.add(node['@id'])
+                    subject = rdf_rest[0]['@id']
+                    node = graph_object.get(subject)
 
-                # convert to @type unless options indicate to treat rdf:type as
-                # property
-                if p == RDF_TYPE and not options['useRdfType']:
-                    # add value of object as @type
-                    JsonLdProcessor.add_value(
-                        value, '@type', o['value'], {'propertyIsArray': True})
-                else:
-                    # add property to value as needed
-                    object = self._rdf_to_object(o, options['useNativeTypes'])
-                    JsonLdProcessor.add_value(
-                        value, p, object, {'propertyIsArray': True})
-
-                    # bnode might be the start of a list, so add it to list map
-                    if o['type'] == 'blank node':
-                        id_ = object['@id']
-                        # create list entry as needed
-                        list_map = graph['listMap']
-                        entry = list_map.setdefault(id_, {})
-                        entry['head'] = object
-
-        # build @lists
-        for name, graph in graphs.items():
-            # find list head
-            list_map = graph['listMap']
-            for subject, entry in list_map.items():
-                # head found, build lists
-                if 'head' in entry and 'first' in entry:
-                    # replace bnode @id with @list
-                    value = entry['head']
-                    del value['@id']
-                    list_ = value['@list'] = [entry['first']]
-                    while 'rest' in entry:
-                        rest = entry['rest']
-                        entry = list_map[rest]
-                        if 'first' not in entry:
-                            raise JsonLdError(
-                                'Invalid RDF list entry.',
-                                'jsonld.RdfError', {'bnode': rest})
-                        list_.append(entry['first'])
-
-        # build default graph in subject @id order
-        output = []
-        for id_, subject in sorted(default_graph['subjects'].items()):
-            # add subject to default graph
-            output.append(subject)
-
-            # output named graph in subject @id order
-            if id_ in graphs:
-                graph = subject['@graph'] = []
-                for id_, subject in sorted(graphs[id_]['subjects'].items()):
-                    graph.append(subject)
-        return output
+                # bad list detected, skip it
+                if list is None:
+                    continue
+
+                del value['@id']
+                value['@list'] = list
+                for id in eliminated_nodes:
+                    del graph_object[id]
+
+        result = []
+        for subject, node in sorted(default_graph.items()):
+            if subject in graph_map:
+                graph = node['@graph'] = []
+                for s, n in sorted(graph_map[subject].items()):
+                    n.pop('listHeadFor', None)
+                    graph.append(n)
+            node.pop('listHeadFor', None)
+            result.append(node)
+
+        return result
 
     def _process_context(self, active_ctx, local_ctx, options):
         """
@@ -2373,10 +2382,6 @@ class JsonLdProcessor:
 
         :return: the JSON-LD object.
         """
-        # convert empty list
-        if o['type'] == 'IRI' and o['value'] == RDF_NIL:
-            return {'@list': []}
-
         # convert IRI/BlankNode object to JSON-LD
         if o['type'] == 'IRI' or o['type'] == 'blank node':
             return {'@id': o['value']}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-pyld.git



More information about the Python-modules-commits mailing list