[Python-modules-commits] [python-pyld] 18/276: Added support for keyword aliasing.
Wolfgang Borgert
debacle at moszumanska.debian.org
Wed Oct 8 23:47:49 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 9c0532ea46fe9a4508299d77f2c1efb9d9f2ce53
Author: Dave Longley <dlongley at digitalbazaar.com>
Date: Mon Aug 22 01:53:18 2011 -0400
Added support for keyword aliasing.
---
lib/pyld/jsonld.py | 706 +++++++++++++++++++++++++++++------------------------
1 file changed, 382 insertions(+), 324 deletions(-)
diff --git a/lib/pyld/jsonld.py b/lib/pyld/jsonld.py
index df305ff..1f77dd2 100644
--- a/lib/pyld/jsonld.py
+++ b/lib/pyld/jsonld.py
@@ -10,12 +10,6 @@
# Copyright (c) 2011 Digital Bazaar, Inc. All rights reserved.
import copy
-# DEBUG:
-import json
-
-_s = '@subject'
-_t = '@type'
-
ns = {
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'xsd': 'http://www.w3.org/2001/XMLSchema#'
@@ -30,6 +24,54 @@ xsd = {
}
##
+# Sets a subject's property to the given object value. If a value already
+# exists, it will be appended to an array.
+#
+# @param s the subject.
+# @param p the property.
+# @param o the object.
+def _setProperty(s, p, o):
+ if p in s:
+ if isinstance(s[p], list):
+ s[p].append(o)
+ else:
+ s[p] = [s[p], o]
+ else:
+ s[p] = o
+
+##
+# Gets the keywords from a context.
+#
+# @param ctx the context.
+#
+# @return the keywords.
+def _getKeywords(ctx):
+ # TODO: reduce calls to this function by caching keywords in processor
+ # state
+
+ rval = {
+ '@datatype': '@datatype',
+ '@iri': '@iri',
+ '@language': '@language',
+ '@literal': '@literal',
+ '@subject': '@subject',
+ '@type': '@type'
+ }
+
+ if ctx:
+ # gather keyword aliases from context
+ keywords = {}
+ for key, value in ctx.items():
+ if isinstance(value, (str, unicode)) and value in rval:
+ keywords[value] = key
+
+ # overwrite keywords
+ for key in keywords:
+ rval[key] = keywords[key]
+
+ return rval
+
+##
# Compacts an IRI into a term or CURIE if it can be. IRIs will not be
# compacted to relative IRIs if they match the given context's default
# vocabulary.
@@ -56,7 +98,7 @@ def _compactIri(ctx, iri, usedCtx):
# term not found, if term is rdf type, use built-in keyword
if rval is None and iri == ns['rdf'] + 'type':
- rval = _t
+ rval = _getKeywords(ctx)['@type']
# term not found, check the context for a CURIE prefix
if rval is None:
@@ -93,6 +135,9 @@ def _compactIri(ctx, iri, usedCtx):
def _expandTerm(ctx, term, usedCtx):
rval = None
+ # get JSON-LD keywords
+ keywords = _getKeywords(ctx)
+
# 1. If the property has a colon, then it is a CURIE or an absolute IRI:
idx = term.find(':')
if idx != -1:
@@ -114,14 +159,14 @@ def _expandTerm(ctx, term, usedCtx):
if usedCtx is not None:
usedCtx[term] = rval
# 3. The property is the special-case subject.
- elif term == _s:
- rval = _s
+ elif term == keywords['@subject']:
+ rval = keywords['@subject']
# 4. The property is the special-case rdf type.
- elif term == _t:
+ elif term == keywords['@type']:
rval = ns['rdf'] + 'type'
# 5. The property is a relative IRI, prepend the default vocab.
else:
- rval = term;
+ rval = term
if '@vocab' in ctx:
rval = ctx['@vocab'] + rval
if usedCtx is not None:
@@ -130,264 +175,6 @@ def _expandTerm(ctx, term, usedCtx):
return rval
##
-# Sets a subject's property to the given object value. If a value already
-# exists, it will be appended to an array.
-#
-# @param s the subject.
-# @param p the property.
-# @param o the object.
-def _setProperty(s, p, o):
- if p in s:
- if isinstance(s[p], list):
- s[p].append(o)
- else:
- s[p] = [s[p], o]
- else:
- s[p] = o
-
-##
-# Gets the coerce type for the given property.
-#
-# @param ctx the context to use.
-# @param property the property to get the coerced type for.
-# @param usedCtx a context to update if a value was used from "ctx".
-#
-# @return the coerce type, None for none.
-def _getCoerceType(ctx, property, usedCtx):
- rval = None
-
- # get expanded property
- p = _expandTerm(ctx, property, None)
-
- # built-in type coercion JSON-LD-isms
- if p == _s or p == ns['rdf'] + 'type':
- rval = xsd['anyURI']
-
- # check type coercion for property
- elif '@coerce' in ctx:
- # force compacted property
- p = _compactIri(ctx, p, None)
-
- for type in ctx['@coerce']:
- # get coerced properties (normalize to an array)
- props = ctx['@coerce'][type]
- if not isinstance(props, list):
- props = [props]
-
- # look for the property in the array
- for i in props:
- # property found
- if i == p:
- rval = _expandTerm(ctx, type, usedCtx)
- if usedCtx is not None:
- if '@coerce' not in usedCtx:
- usedCtx['@coerce'] = {}
-
- if type not in usedCtx['@coerce']:
- usedCtx['@coerce'][type] = p
- else:
- c = usedCtx['@coerce'][type]
- if ((isinstance(c, list) and c.find(p) == -1) or
- (isinstance(c, (str, unicode)) and c != p)):
- _setProperty(usedCtx['@coerce'], type, p)
- break
-
- return rval
-
-##
-# Recursively compacts a value. This method will compact IRIs to CURIEs or
-# terms and do reverse type coercion to compact a value.
-#
-# @param ctx the context to use.
-# @param property the property that points to the value, NULL for none.
-# @param value the value to compact.
-# @param usedCtx a context to update if a value was used from "ctx".
-#
-# @return the compacted value.
-def _compact(ctx, property, value, usedCtx):
- rval = None
-
- if value is None:
- # return None, but check coerce type to add to usedCtx
- rval = None
- _getCoerceType(ctx, property, usedCtx)
- elif isinstance(value, list):
- # recursively add compacted values to array
- rval = []
- for i in value:
- rval.append(_compact(ctx, property, i, usedCtx))
- # graph literal/disjoint graph
- elif (isinstance(value, dict) and _s in value and
- isinstance(value[_s], list)):
- rval = {}
- rval[_s] = _compact(ctx, property, value[_s], usedCtx)
- # value has sub-properties if it doesn't define a literal or IRI value
- elif (isinstance(value, dict) and '@literal' not in value and
- '@iri' not in value):
- # recursively handle sub-properties that aren't a sub-context
- rval = {}
- for key in value:
- if value[key] != '@context':
- # set object to compacted property, only overwrite existing
- # properties if the property actually compacted
- p = _compactIri(ctx, key, usedCtx)
- if p != key or p not in rval:
- rval[p] = _compact(ctx, key, value[key], usedCtx)
- else:
- # get coerce type
- coerce = _getCoerceType(ctx, property, usedCtx)
-
- # get type from value, to ensure coercion is valid
- type = None
- if isinstance(value, dict):
- # type coercion can only occur if language is not specified
- if '@language' not in value:
- # datatype must match coerce type if specified
- if '@datatype' in value:
- type = value['@datatype']
- # datatype is IRI
- elif '@iri' in value:
- type = xsd['anyURI']
- # can be coerced to any type
- else:
- type = coerce
- # type can be coerced to anything
- elif isinstance(value, (str, unicode)):
- type = coerce
-
- # types that can be auto-coerced from a JSON-builtin
- if coerce is None and (type == xsd['boolean'] or
- type == xsd['integer'] or type == xsd['double']):
- coerce = type
-
- # do reverse type-coercion
- if coerce is not None:
- # type is only None if a language was specified, which is an error
- # if type coercion is specified
- if type is None:
- raise Exception('Cannot coerce type when a language is ' +
- 'specified. The language information would be lost.')
- # if the value type does not match the coerce type, it is an error
- elif type != coerce:
- raise Exception('Cannot coerce type because the datatype ' +
- 'does not match.')
- # do reverse type-coercion
- else:
- if isinstance(value, dict):
- if '@iri' in value:
- rval = value['@iri']
- elif '@literal' in value:
- rval = value['@literal']
- else:
- rval = value
-
- # do basic JSON types conversion
- if coerce == xsd['boolean']:
- rval = (rval == 'true' or rval != 0)
- elif coerce == xsd['double']:
- rval = float(rval)
- elif coerce == xsd['integer']:
- rval = int(rval)
-
- # no type-coercion, just copy value
- else:
- rval = copy.copy(value)
-
- # compact IRI
- if type == xsd['anyURI']:
- if isinstance(rval, dict):
- rval['@iri'] = _compactIri(ctx, rval['@iri'], usedCtx)
- else:
- rval = _compactIri(ctx, rval, usedCtx)
-
- return rval
-
-##
-# Recursively expands a value using the given context. Any context in
-# the value will be removed.
-#
-# @param ctx the context.
-# @param property the property that points to the value, NULL for none.
-# @param value the value to expand.
-# @param expandSubjects True to expand subjects (normalize), False not to.
-#
-# @return the expanded value.
-def _expand(ctx, property, value, expandSubjects):
- rval = None
-
- # TODO: add data format error detection?
-
- # value is null, nothing to expand
- if value is None:
- rval = None
- # if no property is specified and the value is a string (this means the
- # value is a property itself), expand to an IRI
- elif property is None and isinstance(value, (str, unicode)):
- rval = _expandTerm(ctx, value, None)
- elif isinstance(value, list):
- # recursively add expanded values to array
- rval = []
- for i in value:
- rval.append(_expand(ctx, property, i, expandSubjects))
- elif isinstance(value, dict):
- # value has sub-properties if it doesn't define a literal or IRI value
- if not ('@literal' in value or '@iri' in value):
- # if value has a context, use it
- if '@context' in value:
- ctx = mergeContexts(ctx, value['@context'])
-
- # recursively handle sub-properties that aren't a sub-context
- rval = {}
- for key in value:
- # preserve frame keywords
- if (key == '@embed' or key == '@explicit' or
- key == '@default' or key == '@omitDefault'):
- _setProperty(rval, key, copy.copy(value[key]))
- elif key != '@context':
- # set object to expanded property
- _setProperty(rval, _expandTerm(ctx, key, None),
- _expand(ctx, key, value[key], expandSubjects))
- # value is already expanded
- else:
- rval = copy.copy(value)
- else:
- # do type coercion
- coerce = _getCoerceType(ctx, property, None)
-
- # automatic coercion for basic JSON types
- if coerce is None and isinstance(value, (int, long, float, bool)):
- if isinstance(value, bool):
- coerce = xsd['boolean']
- elif isinstance(value, float):
- coerce = xsd['double']
- else:
- coerce = xsd['integer']
-
- # coerce to appropriate datatype, only expand subjects if requested
- if coerce is not None and (property != _s or expandSubjects):
- rval = {}
-
- # expand IRI
- if coerce == xsd['anyURI']:
- rval['@iri'] = _expandTerm(ctx, value, None)
- # other datatype
- else:
- rval['@datatype'] = coerce
- if coerce == xsd['double']:
- # do special JSON-LD double format
- value = '%1.6e' % value
- elif coerce == xsd['boolean']:
- value = 'true' if value else 'false'
- else:
- value = '%s' % value
- rval['@literal'] = value
- # nothing to coerce
- else:
- rval = '' + value
-
- return rval
-
-##
# Checks if is blank node IRI.
def _isBlankNodeIri(v):
return v.find('_:') == 0
@@ -396,15 +183,15 @@ def _isBlankNodeIri(v):
# Checks if is named blank node.
def _isNamedBlankNode(v):
# look for "_:" at the beginning of the subject
- return (isinstance(v, dict) and _s in v and
- '@iri' in v[_s] and _isBlankNodeIri(v[_s]['@iri']))
+ return (isinstance(v, dict) and '@subject' in v and
+ '@iri' in v['@subject'] and _isBlankNodeIri(v['@subject']['@iri']))
##
# Checks if is blank node.
def _isBlankNode(v):
# look for no subject or named blank node
return (isinstance(v, dict) and not ('@iri' in v or '@literal' in v) and
- (_s not in v or _isNamedBlankNode(v)))
+ ('@subject' not in v or _isNamedBlankNode(v)))
##
# Compares two values.
@@ -575,13 +362,13 @@ def _collectSubjects(input, subjects, bnodes):
for i in input:
_collectSubjects(i, subjects, bnodes)
elif isinstance(input, dict):
- if _s in input:
+ if '@subject' in input:
# graph literal
- if isinstance(input[_s], list):
- _collectSubjects(input[_s], subjects, bnodes)
+ if isinstance(input['@subject'], list):
+ _collectSubjects(input['@subject'], subjects, bnodes)
# named subject
else:
- subjects[input[_s]['@iri']] = input
+ subjects[input['@subject']['@iri']] = input
# unnamed blank node
elif _isBlankNode(input):
bnodes.append(input)
@@ -611,13 +398,13 @@ def _flatten(parent, parentProperty, value, subjects):
_flatten(parent, parentProperty, i, subjects)
elif isinstance(value, dict):
# graph literal/disjoint graph
- if _s in value and isinstance(value[_s], list):
+ if '@subject' in value and isinstance(value['@subject'], list):
# cannot flatten embedded graph literals
if parent is not None:
raise Exception('Embedded graph literals cannot be flattened.')
# top-level graph literal
- for key in value[_s]:
+ for key in value['@subject']:
_flatten(parent, parentProperty, key, subjects)
# already-expanded value
elif '@literal' in value or '@iri' in value:
@@ -626,14 +413,14 @@ def _flatten(parent, parentProperty, value, subjects):
else:
# create or fetch existing subject
subject = None
- if value[_s]['@iri'] in subjects:
- # FIXME: _s might be a graph literal (as {})
- subject = subjects[value[_s]['@iri']]
+ if value['@subject']['@iri'] in subjects:
+ # FIXME: '@subject' might be a graph literal (as {})
+ subject = subjects[value['@subject']['@iri']]
else:
subject = {}
- if _s in value:
- # FIXME: _s might be a graph literal (as {})
- subjects[value[_s]['@iri']] = subject
+ if '@subject' in value:
+ # FIXME: '@subject' might be a graph literal (as {})
+ subjects[value['@subject']['@iri']] = subject
flattened = subject
# flatten embeds
@@ -656,12 +443,12 @@ def _flatten(parent, parentProperty, value, subjects):
# add flattened value to parent
if flattened is not None and parent is not None:
- # remove top-level _s for subjects
+ # remove top-level '@subject' for subjects
# 'http://mypredicate': {'@subject': {'@iri': 'http://mysubject'}}
# becomes
# 'http://mypredicate': {'@iri': 'http://mysubject'}
- if isinstance(flattened, dict) and _s in flattened:
- flattened = flattened[_s]
+ if isinstance(flattened, dict) and '@subject' in flattened:
+ flattened = flattened['@subject']
if isinstance(parent, list):
# do not add duplicate IRIs for the same property
@@ -731,8 +518,226 @@ class Processor:
##
# Initialize the JSON-LD processor.
def __init__(self):
- self.tmp = None
- self.c14n = None
+ pass
+
+ ##
+ # Recursively compacts a value. This method will compact IRIs to CURIEs or
+ # terms and do reverse type coercion to compact a value.
+ #
+ # @param ctx the context to use.
+ # @param property the property that points to the value, NULL for none.
+ # @param value the value to compact.
+ # @param usedCtx a context to update if a value was used from "ctx".
+ #
+ # @return the compacted value.
+ def compact(self, ctx, property, value, usedCtx):
+ rval = None
+
+ # get JSON-LD keywords
+ keywords = _getKeywords(ctx)
+
+ if value is None:
+ # return None, but check coerce type to add to usedCtx
+ rval = None
+ self.getCoerceType(ctx, property, usedCtx)
+ elif isinstance(value, list):
+ # recursively add compacted values to array
+ rval = []
+ for i in value:
+ rval.append(self.compact(ctx, property, i, usedCtx))
+ # graph literal/disjoint graph
+ elif (isinstance(value, dict) and '@subject' in value and
+ isinstance(value['@subject'], list)):
+ rval = {}
+ rval[keywords['@subject']] = self.compact(
+ ctx, property, value['@subject'], usedCtx)
+ # value has sub-properties if it doesn't define a literal or IRI value
+ elif (isinstance(value, dict) and '@literal' not in value and
+ '@iri' not in value):
+ # recursively handle sub-properties that aren't a sub-context
+ rval = {}
+ for key in value:
+ if value[key] != '@context':
+ # set object to compacted property, only overwrite existing
+ # properties if the property actually compacted
+ p = _compactIri(ctx, key, usedCtx)
+ if p != key or p not in rval:
+ rval[p] = self.compact(ctx, key, value[key], usedCtx)
+ else:
+ # get coerce type
+ coerce = self.getCoerceType(ctx, property, usedCtx)
+
+ # get type from value, to ensure coercion is valid
+ type = None
+ if isinstance(value, dict):
+ # type coercion can only occur if language is not specified
+ if '@language' not in value:
+ # datatype must match coerce type if specified
+ if '@datatype' in value:
+ type = value['@datatype']
+ # datatype is IRI
+ elif '@iri' in value:
+ type = xsd['anyURI']
+ # can be coerced to any type
+ else:
+ type = coerce
+ # type can be coerced to anything
+ elif isinstance(value, (str, unicode)):
+ type = coerce
+
+ # types that can be auto-coerced from a JSON-builtin
+ if coerce is None and (type == xsd['boolean'] or
+ type == xsd['integer'] or type == xsd['double']):
+ coerce = type
+
+ # do reverse type-coercion
+ if coerce is not None:
+ # type is only None if a language was specified, which is an
+ # error if type coercion is specified
+ if type is None:
+ raise Exception('Cannot coerce type when a language is ' +
+ 'specified. The language information would be lost.')
+ # if the value type does not match the coerce type, it is an
+ # error
+ elif type != coerce:
+ raise Exception('Cannot coerce type because the ' +
+ 'datatype does not match.')
+ # do reverse type-coercion
+ else:
+ if isinstance(value, dict):
+ if '@iri' in value:
+ rval = value['@iri']
+ elif '@literal' in value:
+ rval = value['@literal']
+ else:
+ rval = value
+
+ # do basic JSON types conversion
+ if coerce == xsd['boolean']:
+ rval = (rval == 'true' or rval != 0)
+ elif coerce == xsd['double']:
+ rval = float(rval)
+ elif coerce == xsd['integer']:
+ rval = int(rval)
+
+ # no type-coercion, just change keywords/copy value
+ elif isinstance(value, dict):
+ rval = {}
+ for key, v in value.items():
+ rval[keywords[key]] = v
+ else:
+ rval = copy.copy(value)
+
+ # compact IRI
+ if type == xsd['anyURI']:
+ if isinstance(rval, dict):
+ rval[keywords['@iri']] = _compactIri(
+ ctx, rval[keywords['@iri']], usedCtx)
+ else:
+ rval = _compactIri(ctx, rval, usedCtx)
+
+ return rval
+
+ ##
+ # Recursively expands a value using the given context. Any context in
+ # the value will be removed.
+ #
+ # @param ctx the context.
+ # @param property the property that points to the value, NULL for none.
+ # @param value the value to expand.
+ # @param expandSubjects True to expand subjects (normalize), False not to.
+ #
+ # @return the expanded value.
+ def expand(self, ctx, property, value, expandSubjects):
+ rval = None
+
+ # TODO: add data format error detection?
+
+ # value is null, nothing to expand
+ if value is None:
+ rval = None
+ # if no property is specified and the value is a string (this means the
+ # value is a property itself), expand to an IRI
+ elif property is None and isinstance(value, (str, unicode)):
+ rval = _expandTerm(ctx, value, None)
+ elif isinstance(value, list):
+ # recursively add expanded values to array
+ rval = []
+ for i in value:
+ rval.append(self.expand(ctx, property, i, expandSubjects))
+ elif isinstance(value, dict):
+ # if value has a context, use it
+ if '@context' in value:
+ ctx = mergeContexts(ctx, value['@context'])
+
+ # get JSON-LD keywords
+ keywords = _getKeywords(ctx)
+
+ # value has sub-properties if it doesn't define a literal or IRI
+ # value
+ if not (keywords['@literal'] in value or keywords['@iri'] in value):
+ # recursively handle sub-properties that aren't a sub-context
+ rval = {}
+ for key in value:
+ # preserve frame keywords
+ if (key == '@embed' or key == '@explicit' or
+ key == '@default' or key == '@omitDefault'):
+ _setProperty(rval, key, copy.copy(value[key]))
+ elif key != '@context':
+ # set object to expanded property
+ _setProperty(rval, _expandTerm(ctx, key, None),
+ self.expand(ctx, key, value[key], expandSubjects))
+ # only need to expand keywords
+ else:
+ rval = {}
+ if keywords['@iri'] in value:
+ rval['@iri'] = value[keywords['@iri']]
+ else:
+ rval['@literal'] = value[keywords['@literal']]
+ if keywords['@language'] in value:
+ rval['@language'] = value[keywords['@language']]
+ elif keywords['@datatype'] in value:
+ rval['@datatype'] = value[keywords['@datatype']]
+ else:
+ # do type coercion
+ coerce = self.getCoerceType(ctx, property, None)
+
+ # get JSON-LD keywords
+ keywords = _getKeywords(ctx)
+
+ # automatic coercion for basic JSON types
+ if coerce is None and isinstance(value, (int, long, float, bool)):
+ if isinstance(value, bool):
+ coerce = xsd['boolean']
+ elif isinstance(value, float):
+ coerce = xsd['double']
+ else:
+ coerce = xsd['integer']
+
+ # coerce to appropriate datatype, only expand subjects if requested
+ if coerce is not None and (
+ property != keywords['@subject'] or expandSubjects):
+ rval = {}
+
+ # expand IRI
+ if coerce == xsd['anyURI']:
+ rval['@iri'] = _expandTerm(ctx, value, None)
+ # other datatype
+ else:
+ rval['@datatype'] = coerce
+ if coerce == xsd['double']:
+ # do special JSON-LD double format
+ value = '%1.6e' % value
+ elif coerce == xsd['boolean']:
+ value = 'true' if value else 'false'
+ else:
+ value = '%s' % value
+ rval['@literal'] = value
+ # nothing to coerce
+ else:
+ rval = '' + value
+
+ return rval
##
# Normalizes a JSON-LD object.
@@ -746,8 +751,12 @@ class Processor:
# TODO: validate context
if input is not None:
+ # create name generator state
+ self.tmp = None
+ self.c14n = None
+
# expand input
- expanded = _expand({}, None, input, True)
+ expanded = self.expand({}, None, input, True)
# assign names to unnamed bnodes
self.nameBlankNodes(expanded)
@@ -769,7 +778,7 @@ class Processor:
self.canonicalizeBlankNodes(rval)
def normalizeSort(a, b):
- return _compare(a[_s]['@iri'], b[_s]['@iri'])
+ return _compare(a['@subject']['@iri'], b['@subject']['@iri'])
# sort output
rval.sort(cmp=normalizeSort)
@@ -777,6 +786,60 @@ class Processor:
return rval
##
+ # Gets the coerce type for the given property.
+ #
+ # @param ctx the context to use.
+ # @param property the property to get the coerced type for.
+ # @param usedCtx a context to update if a value was used from "ctx".
+ #
+ # @return the coerce type, None for none.
+ def getCoerceType(self, ctx, property, usedCtx):
+ rval = None
+
+ # get expanded property
+ p = _expandTerm(ctx, property, None)
+
+ # built-in type coercion JSON-LD-isms
+ if p == '@subject' or p == ns['rdf'] + 'type':
+ rval = xsd['anyURI']
+
+ # check type coercion for property
+ elif '@coerce' in ctx:
+ # force compacted property
+ p = _compactIri(ctx, p, None)
+
+ for type in ctx['@coerce']:
+ # get coerced properties (normalize to an array)
+ props = ctx['@coerce'][type]
+ if not isinstance(props, list):
+ props = [props]
+
+ # look for the property in the array
+ for i in props:
+ # property found
+ if i == p:
+ rval = _expandTerm(ctx, type, usedCtx)
+
+ # '@iri' is shortcut for xsd['anyURI']
+ if rval == '@iri':
+ rval = xsd['anyURI']
+
+ if usedCtx is not None:
+ if '@coerce' not in usedCtx:
+ usedCtx['@coerce'] = {}
+
+ if type not in usedCtx['@coerce']:
+ usedCtx['@coerce'][type] = p
+ else:
+ c = usedCtx['@coerce'][type]
+ if ((isinstance(c, list) and c.find(p) == -1) or
+ (isinstance(c, (str, unicode)) and c != p)):
+ _setProperty(usedCtx['@coerce'], type, p)
+ break
+
+ return rval
+
+ ##
# Assigns unique names to blank nodes that are unnamed in the given input.
#
# @param input the input to assign names to.
@@ -791,11 +854,11 @@ class Processor:
# uniquely name all unnamed bnodes
for bnode in bnodes:
- if not (_s in bnode):
+ if not ('@subject' in bnode):
# generate names until one is unique
while(ng.next() in subjects):
pass
- bnode[_s] = { '@iri': ng.current() }
+ bnode['@subject'] = { '@iri': ng.current() }
subjects[ng.current()] = bnode
##
@@ -805,10 +868,10 @@ class Processor:
# @param b the blank node to rename.
# @param id the new name to use.
def renameBlankNode(self, b, id):
- old = b[_s]['@iri']
+ old = b['@subject']['@iri']
# update bnode IRI
- b[_s]['@iri'] = id
+ b['@subject']['@iri'] = id
# update subjects map
subjects = self.subjects
@@ -869,7 +932,7 @@ class Processor:
subjects = self.subjects = {}
bnodes = []
for s in input:
- iri = s[_s]['@iri']
+ iri = s['@subject']['@iri']
subjects[iri] = s
edges['refs'][iri] = {
'all': [],
@@ -892,12 +955,12 @@ class Processor:
# rename all bnodes that happen to be in the c14n namespace
# and initialize serializations
for bnode in bnodes:
- iri = bnode[_s]['@iri']
+ iri = bnode['@subject']['@iri']
if c14n.inNamespace(iri):
while ngTmp.next() in subjects:
pass
self.renameBlankNode(bnode, ngTmp.current())
- iri = bnode[_s]['@iri']
+ iri = bnode['@subject']['@iri']
self.serializations[iri] = {
'props': None,
'refs': None
@@ -913,7 +976,7 @@ class Processor:
# name all bnodes accoring to the first bnodes relation mappings
bnode = bnodes.pop(0)
- iri = bnode[_s]['@iri']
+ iri = bnode['@subject']['@iri']
dirs = ['props', 'refs']
for dir in dirs:
# if no serialization has been computed,
@@ -943,7 +1006,7 @@ class Processor:
tmp = bnodes
bnodes = []
for b in tmp:
- iriB = b[_s]['@iri']
+ iriB = b['@subject']['@iri']
if not c14n.inNamespace(iriB):
for i2 in renamed:
self.markSerializationDirty(iriB, i2, dir)
@@ -1130,8 +1193,8 @@ class Processor:
rval = 0
# compare IRIs
- iriA = a[_s]['@iri']
- iriB = b[_s]['@iri']
+ iriA = a['@subject']['@iri']
+ iriB = b['@subject']['@iri']
if iriA == iriB:
rval = 0
else:
@@ -1213,8 +1276,8 @@ class Processor:
# step #4
if rval == 0:
- edgesA = self.edges['refs'][a[_s]['@iri']]['all']
- edgesB = self.edges['refs'][b[_s]['@iri']]['all']
+ edgesA = self.edges['refs'][a['@subject']['@iri']]['all']
+ edgesB = self.edges['refs'][b['@subject']['@iri']]['all']
rval = _compare(len(edgesA), len(edgesB))
# step #5
@@ -1278,7 +1341,7 @@ class Processor:
for iri in self.subjects:
subject = self.subjects[iri]
for key in subject:
- if key != _s:
+ if key != '@subject':
# normalize to array for single codepath
object = subject[key]
tmp = [object] if not isinstance(object, list) else object
@@ -1341,7 +1404,7 @@ class Processor:
# build map of all subjects
subjects = {}
for i in input:
- subjects[i[_s]['@iri']] = i
+ subjects[i['@subject']['@iri']] = i
# frame input
rval = _frame(subjects, input, frame, {}, options)
@@ -1366,7 +1429,7 @@ def _isType(src, frame):
# check if type(s) are specified in frame and src
rType = ns['rdf'] + 'type'
- if (rType in frame and isinstance(src, dict) and _s in src and
+ if (rType in frame and isinstance(src, dict) and '@subject' in src and
rType in src):
tmp = src[rType] if isinstance(src[rType], list) else [src[rType]]
types = (frame[rType] if isinstance(frame[rType], list)
@@ -1412,7 +1475,7 @@ def _isDuckType(src, frame):
# src always matches if there are no properties
rval = True
# src must be a subject with all the given properties
- elif isinstance(src, dict) and _s in src:
+ elif isinstance(src, dict) and '@subject' in src:
rval = True
for i in props:
if i not in src:
@@ -1481,20 +1544,20 @@ def _frame(subjects, input, frame, embeds, options):
if not embedOn:
# if value is a subject, only use subject IRI as reference
- if isinstance(value, dict) and _s in value:
- value = value[_s]
- elif (isinstance(value, dict) and _s in value and
- value[_s]['@iri'] in embeds):
+ if isinstance(value, dict) and '@subject' in value:
+ value = value['@subject']
+ elif (isinstance(value, dict) and '@subject' in value and
+ value['@subject']['@iri'] in embeds):
# TODO: possibly support multiple embeds in the future ... and
# instead only prevent cycles?
raise Exception(
'More than one embed of the same subject is not supported.',
- value[_s]['@iri'])
+ value['@subject']['@iri'])
# if value is a subject, do embedding and subframing
- elif isinstance(value, dict) and _s in value:
- embeds[value[_s]['@iri']] = True
+ elif isinstance(value, dict) and '@subject' in value:
+ embeds[value['@subject']['@iri']] = True
# if explicit on, remove keys from value that aren't in frame
explicitOn = (frame['@explicit'] if '@explicit' in frame
@@ -1502,7 +1565,7 @@ def _frame(subjects, input, frame, embeds, options):
if explicitOn:
for key in value.keys():
# do not remove subject or any key in the frame
- if key != _s and key not in frame:
+ if key != '@subject' and key not in frame:
del value[key]
# iterate over frame keys to do subframing
@@ -1632,7 +1695,7 @@ def _compareSerializations(s1, s2):
#
# @return the normalized JSON-LD object.
def normalize(input):
- return Processor().normalize(input)
+ return Processor().normalize(input)
##
# Removes the context from a JSON-LD object, expanding it to full-form.
@@ -1641,12 +1704,7 @@ def normalize(input):
#
# @return the context-neutral JSON-LD object.
def expand(input):
- rval = None
-
- if input is not None:
- rval = _expand({}, None, input, False)
-
- return rval
+ return Processor().expand({}, None, input, False)
##
# Expands the given JSON-LD object and then compacts it using the
@@ -1677,7 +1735,7 @@ def compact(ctx, input):
ctxOut = {}
# compact
- output = _compact(copy.copy(ctx), None, value, ctxOut)
+ output = Processor().compact(copy.copy(ctx), None, value, ctxOut)
# add context if used
if len(ctxOut.keys()) > 0:
--
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