[Python-modules-commits] [python-pyld] 34/276: Updated to new framing algorithm.

Wolfgang Borgert debacle at moszumanska.debian.org
Wed Oct 8 23:47:50 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 fecd234af687846fa086a66c990931e86d3b28d1
Author: Dave Longley <dlongley at digitalbazaar.com>
Date:   Fri Oct 14 17:33:12 2011 -0400

    Updated to new framing algorithm.
---
 lib/pyld/jsonld.py | 225 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 137 insertions(+), 88 deletions(-)

diff --git a/lib/pyld/jsonld.py b/lib/pyld/jsonld.py
index c649431..619f692 100644
--- a/lib/pyld/jsonld.py
+++ b/lib/pyld/jsonld.py
@@ -404,7 +404,7 @@ def _flatten(parent, parentProperty, value, subjects):
     all blank nodes have been uniquely named before this call. Array values for
     properties will be sorted.
 
-    :param parent: the value's parent, NULL for none.
+    :param parent: the value's parent, None for none.
     :param parentProperty: the property relating the value to the parent.
     :param value: the value to flatten.
     :param subjects: the map of subjects to write to.
@@ -412,7 +412,7 @@ def _flatten(parent, parentProperty, value, subjects):
     flattened = None
 
     if value is None:
-        # drop null values
+        # drop None values
         pass
     elif isinstance(value, list):
         # list of objects or a disjoint graph
@@ -447,7 +447,7 @@ def _flatten(parent, parentProperty, value, subjects):
 
             # flatten embeds
             for key, v in value.items():
-                # drop null values
+                # drop None values
                 if v is not None:
                     if key in subject:
                         if not isinstance(subject[key], list):
@@ -554,7 +554,7 @@ class Processor:
         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 property: the property that points to the value, None for none.
         :param value: the value to compact.
         :param usedCtx: a context to update if a value was used from "ctx".
 
@@ -673,7 +673,7 @@ class Processor:
         the value will be removed.
 
         :param ctx: the context.
-        :param property: the property that points to the value, NULL for none.
+        :param property: the property that points to the value, None for none.
         :param value: the value to expand.
         :param expandSubjects: True to expand subjects (normalize), False not to.
 
@@ -683,7 +683,7 @@ class Processor:
 
         # TODO: add data format error detection?
 
-        # value is null, nothing to expand
+        # value is None, nothing to expand
         if value is None:
             rval = None
         # if no property is specified and the value is a string (this means the
@@ -1371,9 +1371,9 @@ class Processor:
         """
         Populates the given reference map with all of the subject edges in the
         graph. The references will be categorized by the direction of the edges,
-        where 'props' is for properties and 'refs' is for references to a subject
-        as an object. The edge direction categories for each IRI will be sorted
-        into groups 'all' and 'bnodes'.
+        where 'props' is for properties and 'refs' is for references to a
+        subject as an object. The edge direction categories for each IRI will
+        be sorted into groups 'all' and 'bnodes'.
         """
         refs = self.edges['refs']
         props = self.edges['props']
@@ -1449,7 +1449,7 @@ class Processor:
             subjects[i['@subject']['@iri']] = i
 
         # frame input
-        rval = _frame(subjects, input, frame, {}, options)
+        rval = _frame(subjects, input, frame, {}, False, None, None, options)
 
         # apply context
         if ctx is not None and rval is not None:
@@ -1530,14 +1530,132 @@ def _isDuckType(src, frame):
 
     return rval
 
-def _frame(subjects, input, frame, embeds, options):
+def _subframe(
+   subjects, value, frame, embeds, autoembed, parent, parentKey, options):
+    """
+    Subframes a value.
+    
+    :param subjects: a map of subjects in the graph.
+    :param value: the value to subframe.
+    :param frame: the frame to use.
+    :param embeds: a map of previously embedded subjects, used to prevent
+       cycles.
+    :param autoembed: true if auto-embed is on, false if not.
+    :param parent: the parent object.
+    :param parentKey: the parent key.
+    :param options: the framing options.
+    
+    :return: the framed input.
+    """
+
+    # get existing embed entry
+    iri = value['@subject']['@iri']
+    embed = embeds[iri] if iri in embeds else None
+
+    # determine if value should be embedded or referenced,
+    # embed is ON if:
+    # 1. The frame OR default option specifies @embed as ON, AND
+    # 2. There is no existing embed OR it is an autoembed, AND
+    #    autoembed mode is off.
+    embedOn = (
+        (('@embed' in frame and frame['@embed'] == True) or
+        options['defaults']['embedOn']) and
+        (embed == None or (embed['autoembed'] and not autoembed)))
+
+    if not embedOn:
+        # not embedding, so only use subject IRI as reference
+        value = value['@subject']
+    else:
+        # create new embed entry
+        if embed is None:
+            embed = {}
+            embeds[iri] = embed
+        # replace the existing embed with a reference
+        elif embed['parent'] is not None:
+            embed['parent'][embed['key']] = value['@subject']
+
+        # update embed entry
+        embed['autoembed'] = autoembed
+        embed['parent'] = parent
+        embed['key'] = parentKey
+
+        # check explicit flag
+        explicitOn = (frame['@explicit'] if '@explicit' in frame
+            else options['defaults']['explicitOn'])
+        if explicitOn:
+            # remove keys from the value that aren't in the frame
+            for key in value.keys():
+                # do not remove @subject or any frame key
+                if key != '@subject' and key not in frame:
+                    del value[key]
+
+        # iterate over keys in value
+        for key, v in value.items():
+            # skip keywords and type
+            if key.find('@') != 0 and key != ns['rdf'] + 'type':
+                # get the subframe if available
+                if key in frame:
+                    f = frame[key]
+                    _autoembed = False
+                # use a catch-all subframe to preserve data from graph
+                else:
+                    f = [] if isinstance(value[key], list) else {}
+                    _autoembed = True
+
+                # build input and do recursion
+                input = (value[key] if isinstance(value[key], list)
+                    else [value[key]])
+                for n in range(0, len(input)):
+                    # replace reference to subject w/subject
+                    if (isinstance(input[n], dict) and
+                        '@iri' in input[n] and
+                        input[n]['@iri'] in subjects):
+                        input[n] = subjects[input[n]['@iri']]
+                value[key] = _frame(
+                    subjects, input, f, embeds, _autoembed,
+                    value, key, options)
+
+        # iterate over frame keys to add any missing values
+        for key, f in frame.items():
+            # skip keywords, type query, and non-None keys in value
+            if (key.find('@') != 0 and key != (ns['rdf'] + 'type') and
+                (key not in value or value[key] is None)):
+                # add empty array to value
+                if isinstance(f, list):
+                    value[key] = []
+                # add default value to value
+                else:
+                    # use first subframe if frame is an array
+                    if isinstance(f, list):
+                        f = f[0] if len(f) > 0 else {}
+
+                    # determine if omit default is on
+                    omitOn = (f['@omitDefault'] if
+                        '@omitDefault' in f
+                        else options['defaults']['omitDefaultOn'])
+                    if not omitOn:
+                        if '@default' in f:
+                            # use specified default value
+                            value[key] = f['@default']
+                        else:
+                            # built-in default value is: None
+                            value[key] = None
+
+    return value
+
+def _frame(
+    subjects, input, frame, embeds, autoembed, parent, parentKey, options):
     """
     Recursively frames the given input according to the given frame.
 
     :param subjects: a map of subjects in the graph.
     :param input: the input to frame.
     :param frame: the frame to use.
-    :param embeds: a map of previously embedded subjects, used to prevent cycles.
+    :param embeds: a map of previously embedded subjects, used to prevent
+       cycles.
+    :param autoembed: true if auto-embed is on, false if not.
+    :param parent: the parent object (for subframing).
+    :param parentKey: the parent key (for subframing).
     :param options: the framing options.
 
     :return: the framed input.
@@ -1566,7 +1684,7 @@ def _frame(subjects, input, frame, embeds, options):
         # get next frame
         frame = frames[i]
         if not isinstance(frame, (list, dict)):
-            raise Exception('Invalid JSON-LD frame. Frame type is not a map' +
+            raise Exception('Invalid JSON - LD frame. Frame type is not a map' +
                'or array.')
 
         # create array of values for each frame
@@ -1589,80 +1707,11 @@ def _frame(subjects, input, frame, embeds, options):
     # for each matching value, add it to the output
     for frame, vals in zip(frames, values):
         for value in vals:
-            # determine if value should be embedded or referenced
-            embedOn = (frame['@embed'] if '@embed' in frame
-                else options['defaults']['embedOn'])
-
-            if not embedOn:
-                # if value is a subject, only use subject IRI as reference 
-                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['@subject']['@iri'])
-
-            # if value is a subject, do embedding and subframing
-            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
-                    else options['defaults']['explicitOn'])
-                if explicitOn:
-                    for key in value.keys():
-                        # do not remove subject or any key in the frame
-                        if key != '@subject' and key not in frame:
-                            del value[key]
-
-                # iterate over frame keys to do subframing
-                for key, f in frame.items():
-                    # skip keywords and type query
-                    if key.find('@') != 0 and key != ns['rdf'] + 'type':
-                        if key in value:
-                            # build input and do recursion
-                            input = (value[key] if isinstance(value[key], list)
-                                else [value[key]])
-                            for n in range(0, len(input)):
-                                # replace reference to subject w/subject
-                                if (isinstance(input[n], dict) and
-                                    '@iri' in input[n] and
-                                    input[n]['@iri'] in subjects):
-                                    input[n] = subjects[input[n]['@iri']]
-                            result = _frame(subjects, input, f, embeds, options)
-                            if result is not None:
-                                value[key] = result
-                            elif omitOn:
-                                # omit is on, remove key
-                                del value[key]
-                            else:
-                                # use specified default from frame if available
-                                if isinstance(f, list):
-                                    f = f[0] if len(f) > 0 else {}
-                                    value[key] = (f['@default'] if
-                                        '@default' in f else None)
-                        else:
-                            # add empty array/null property to value
-                            value[key] = [] if isinstance(f, list) else None
-
-                        # handle setting default value
-                        if value[key] is None:
-                            # use first subframe if frame is an array
-                            if isinstance(f, list):
-                                f = f[0] if len(f) > 0 else {}
-
-                            # determine if omit default is on
-                            omitOn = (f['@omitDefault'] if
-                                '@omitDefault' in f
-                                else options['defaults']['omitDefaultOn'])
-                            if omitOn:
-                                del value[key]
-                            elif '@default' in f:
-                                value[key] = f['@default']
+            # if value is a subject, do subframing
+            if isinstance(value, dict) and '@subject' in value:
+                value = _subframe(
+                    subjects, value, frame, embeds, autoembed,
+                    parent, parentKey, options)
 
             # add value to output
             if rval is None:
@@ -1940,7 +1989,7 @@ def triples(input, callback=_defaultTriplesCallback):
     Generates triples given a JSON-LD input. Each triple that is generated
     results in a call to the given callback. The callback takes 3 parameters:
     subject, property, and object. If the callback returns False then this
-    method will stop generating triples and return. If the callback is null,
+    method will stop generating triples and return. If the callback is None,
     then triple objects containing "s", "p", "o" properties will be generated.
 
     The object or "o" property will be a JSON-LD formatted object.

-- 
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