diff options
Diffstat (limited to 'examples/freebase-images-appengine/freebase/fcl/inspect.py')
| -rwxr-xr-x | examples/freebase-images-appengine/freebase/fcl/inspect.py | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/examples/freebase-images-appengine/freebase/fcl/inspect.py b/examples/freebase-images-appengine/freebase/fcl/inspect.py new file mode 100755 index 0000000..8cd04d2 --- /dev/null +++ b/examples/freebase-images-appengine/freebase/fcl/inspect.py @@ -0,0 +1,218 @@ +# ================================================================== +# Copyright (c) 2007,2008,2009 Metaweb Technologies, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY METAWEB TECHNOLOGIES AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL METAWEB +# TECHNOLOGIES OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ==================================================================== + + +# +# +# wrap all the nastiness needed for a general mql inspect query +# +# + +import os, sys, re + + +null = None +true = True +false = False + +inspect_query = { + 'name': null, + 'type': [], + + '/type/reflect/any_master': [{ + 'optional':true, + 'id': null, + 'name': null, + 'link': { + 'master_property': { + 'id': null, + 'schema': null + } + } + }], + + '/type/reflect/any_reverse': [{ + 'optional':true, + 'id': null, + 'name': null, + 'link': { + 'master_property': { + 'id':null, + 'schema': null, + 'expected_type': null, + 'reverse_property': { + 'id': null, + 'schema': null, + 'optional': true + } + } + } + }], + + '/type/reflect/any_value': [{ + 'optional':true, + 'value': null, + 'link': { + 'master_property': { + 'id':null, + 'schema': null, + 'expected_type': null + }, + } + }], + + 't:/type/reflect/any_value': [{ + 'optional':true, + 'type': '/type/text', + 'value': null, + 'lang': null, + 'link': { + 'master_property': { + 'id':null, + 'schema': null + }, + } + }], + + '/type/object/creator': [{ + 'optional':true, + 'id':null, + 'name':null + }], + '/type/object/timestamp': [{ + 'optional':true, + 'value': null, + }], + + '/type/object/key': [{ + 'optional':true, + 'value': null, + 'namespace': null + }], + '/type/namespace/keys': [{ + 'optional':true, + 'value': null, + 'namespace': null + }] +} + + +def transform_result(result): + proptypes = {} + props = {} + + # copy a property from a /type/reflect clause + def pushtype(propdesc, prop): + tid = propdesc['schema'] + propid = propdesc['id'] + + if isinstance(prop, dict): + prop = dict(prop) + if 'link' in prop: + prop.pop('link') + + if tid not in proptypes: + proptypes[tid] = {} + if propid not in proptypes[tid]: + proptypes[tid][propid] = [] + + if propid not in props: + props[propid] = [] + props[propid].append(prop) + + # copy a property that isn't enumerated by /type/reflect + def pushprop(propid): + ps = result[propid] + if ps is None: + return + + # hack to infer the schema from id, not always reliable! + schema = re.sub(r'/[^/]+$', '', propid) + keyprop = dict(id=propid, schema=schema) + for p in ps: + pushtype(keyprop, p) + + ps = result['/type/reflect/any_master'] or [] + for p in ps: + propdesc = p.link.master_property + pushtype(propdesc, p) + + # non-text non-key values + ps = result['/type/reflect/any_value'] or [] + for p in ps: + propdesc = p.link.master_property + + # /type/text values are queried specially + # so that we can get the lang, so ignore + # them here. + if propdesc.expected_type == '/type/text': + continue + + pushtype(propdesc, p) + + # text values + ps = result['t:/type/reflect/any_value'] or [] + for p in ps: + propdesc = p.link.master_property + pushtype(propdesc, p) + + pushprop('/type/object/creator') + pushprop('/type/object/timestamp') + pushprop('/type/object/key') + pushprop('/type/namespace/keys') + + # now the reverse properties + ps = result['/type/reflect/any_reverse'] or [] + for prop in ps: + propdesc = prop.link.master_property.reverse_property + + # synthetic property descriptor for the reverse of + # a property with no reverse descriptor. + # note the bogus id starting with '-'. + if propdesc is None: + # schema = prop.link.master_property.expected_type + # if schema is None: + # schema = 'other' + + schema = 'other' + propdesc = dict(id='-' + prop.link.master_property.id, + schema=schema) + + pushtype(propdesc, prop) + + #return proptypes + return props + + +def inspect_object(mss, id): + q = dict(inspect_query) + q['id'] = id + r = mss.mqlread(q) + if r is None: + return None + return transform_result(r) |
