[Python-modules-commits] [python-pyld] 163/276: Add support for partial lists.
Wolfgang Borgert
debacle at moszumanska.debian.org
Wed Oct 8 23:48:06 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 28e40b7eff544593cbfc93283d1d98c4be61b902
Author: Dave Longley <dlongley at digitalbazaar.com>
Date: Fri Aug 9 01:46:04 2013 -0400
Add support for partial lists.
---
lib/pyld/jsonld.py | 146 +++++++++++++++++++++++++++++------------------------
1 file changed, 79 insertions(+), 67 deletions(-)
diff --git a/lib/pyld/jsonld.py b/lib/pyld/jsonld.py
index 82bbbf9..24f2843 100644
--- a/lib/pyld/jsonld.py
+++ b/lib/pyld/jsonld.py
@@ -36,11 +36,13 @@ XSD_INTEGER = 'http://www.w3.org/2001/XMLSchema#integer'
XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string'
# RDF constants
-RDF_FIRST = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first'
-RDF_REST = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest'
-RDF_NIL = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'
-RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'
-RDF_LANGSTRING = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'
+RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
+RDF_LIST = RDF + 'List'
+RDF_FIRST = RDF + 'first'
+RDF_REST = RDF + 'rest'
+RDF_NIL = RDF + 'nil'
+RDF_TYPE = RDF + 'type'
+RDF_LANGSTRING = RDF + 'langString'
# JSON-LD keywords
KEYWORDS = [
@@ -1316,7 +1318,7 @@ class JsonLdProcessor:
if t1['object'].get('language') != t2['object'].get('language'):
return False
- if t1['object']['datatype'] != t2['object']['datatype']:
+ if t1['object'].get('datatype') != t2['object'].get('datatype'):
return False
return True
@@ -1844,10 +1846,12 @@ class JsonLdProcessor:
graph_subject = default_graph.setdefault(
graph_name, {'@id': graph_name, '@graph': []})
graph_subject.setdefault('@graph', []).extend(
- [v for k, v in sorted(node_map.items())])
+ [v for k, v in sorted(node_map.items())
+ if not _is_subject_reference(v)])
# produce flattened output
- return [value for key, value in sorted(default_graph.items())]
+ return [value for key, value in sorted(default_graph.items())
+ if not _is_subject_reference(value)]
def _frame(self, input_, frame, options):
"""
@@ -2023,8 +2027,7 @@ class JsonLdProcessor:
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):
+ if object_is_id and o['value'] not in node_map:
node_map[o['value']] = {'@id': o['value']}
if p == RDF_TYPE and object_is_id:
@@ -2032,85 +2035,94 @@ class JsonLdProcessor:
node, '@type', o['value'], {'propertyIsArray': True})
continue
- 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'])
+ 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 may be an RDF list/partial list node but we
+ # can't know easily until all triples are read
+ if object_is_id:
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
+ if 'usages' not in object:
+ object['usages'] = []
+ object['usages'].append({
+ 'node': node,
+ 'property': p,
+ 'value': value
+ })
# 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
+ # no @lists to be converted, continue
+ if RDF_NIL not in graph_object:
+ continue
- 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 {}
+ # iterate backwards through each RDF list
+ nil = graph_object[RDF_NIL]
+ for usage in nil['usages']:
+ node = usage['node']
+ property = usage['property']
+ head = usage['value']
+ list_ = []
+ list_nodes = []
+
+ # ensure node is a well-formed list node; it must:
+ # 1. Be used only once in a list.
+ # 2. Have an array for rdf:first that has 1 item.
+ # 3. Have an array for rdf:rest that has 1 item
+ # 4. Have no keys other than: @id, usages, rdf:first, rdf:rest
+ # and, optionally, @type where the value is rdf:List.
+ node_key_count = len(node.keys())
+ while(property == RDF_REST and len(node['usages']) and
+ _is_array(node[RDF_FIRST]) and len(node[RDF_FIRST]) == 1 and
+ _is_array(node[RDF_REST]) and len(node[RDF_REST]) == 1 and
+ (node_key_count == 4 or (node_key_count == 5 and
+ _is_array(node.get('@type')) and
+ len(node['@type']) == 1 and
+ node['@type'][0] == RDF_LIST))):
+ list_.append(node[RDF_FIRST][0])
+ list_nodes.append(node['@id'])
+
+ # get next node, moving backwards through list
+ usage = node['usages'][0]
+ node = usage['node']
+ property = usage['property']
+ head = usage['value']
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
+
+ # if node is not a blank node, then list head found
+ if not node['@id'].startswith('_:'):
break
- list.append(rdf_first[0])
- eliminated_nodes.add(node['@id'])
- subject = rdf_rest[0]['@id']
- node = graph_object.get(subject)
+ # the list is nested in another list
+ if property == RDF_FIRST:
+ # empty list
+ if node['@id'] == RDF_NIL:
+ # can't convert rdf:nil to a @list object because it
+ # would result in a list of lists which isn't supported
+ continue
- # bad list detected, skip it
- if list is None:
- continue
+ # preserve list head
+ head = graph_object[head['@id']][RDF_REST][0]
+ list_.pop()
+ list_nodes.pop()
- del value['@id']
- value['@list'] = list
- for id_ in eliminated_nodes:
- del graph_object[id_]
+ # transform list into @list object
+ del head['@id']
+ head['@list'] = list_.reverse()
+ for node in list_nodes:
+ graph_object.pop(node, None)
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)
+ n.pop('usages', None)
# only add full subjects to top-level
if not _is_subject_reference(n):
graph.append(n)
- node.pop('listHeadFor', None)
+ node.pop('usages', None)
# only add full subjects to top-level
if not _is_subject_reference(node):
result.append(node)
--
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