summaryrefslogtreecommitdiff
path: root/schema-manipulation/get_type.py
diff options
context:
space:
mode:
Diffstat (limited to 'schema-manipulation/get_type.py')
-rw-r--r--schema-manipulation/get_type.py332
1 files changed, 259 insertions, 73 deletions
diff --git a/schema-manipulation/get_type.py b/schema-manipulation/get_type.py
index af4554e..80def68 100644
--- a/schema-manipulation/get_type.py
+++ b/schema-manipulation/get_type.py
@@ -1,18 +1,217 @@
# TODO: copy /freebase/type_hints junk
+# TODO: preserve property order.
from pprint import pprint
import random
+import json
-from type_creation import create_type, create_property, delegate_property, reciprocate_property
-
+from freebase.schema import TYPE_QUERY, PROPERTY_QUERY
from freebase.api import HTTPMetawebSession, MetawebError
+from freebase.schema import create_type, create_property, reciprocate_property, delegate_property
+
s = HTTPMetawebSession("http://sandbox-freebase.com")
-s.login("username", "password")
+s.login("nitromaster101@gmail.com", "something")
import time
-def create_type_dependencies(s, base_id=None, type_id=None):
+def dump_base(s, base_id):
+ types = map(lambda x: x["id"], s.mqlread({"id" : base_id, "/type/domain/types":[{"id" : None}]})["/type/domain/types"])
+ graph = _get_graph(types)
+ graph["__follow_types"] = True
+
+ return graph
+
+def dump_type(s, type_id, follow_types=True):
+ types = [type_id]
+ graph = _get_graph(types, follow_types)
+ graph["__follow_types"] = follow_types
+ result = json.dumps(graph, indent=2)
+
+ fh = open("junk.json", "w")
+ fh.write(result)
+ fh.close()
+
+ return graph
+
+
+def upload_type(s, graph, new_location, ignore_types=None, debug=False):
+ follow_types = graph.get("__follow_types", True)
+ if debug: print "Following types:", follow_types
+
+ # create type dependencies
+ typegraph = {}
+ for tid, idres in graph.items():
+ if not tid.startswith("__"):
+ typegraph[tid] = idres["__requires"]
+
+ type_deps = map(lambda (name, x): (len(x), name), typegraph.items())
+ type_deps.sort()
+ if follow_types:
+ types_to_create = create_what(type_deps, typegraph)
+ else:
+ types_to_create = typegraph.keys()
+
+ # create property dependencies
+ propgraph = {}
+ proptotype = {}
+ for tid, idres in graph.items():
+ if not tid.startswith("__"):
+ for prop in idres["properties"]:
+ propgraph[prop["id"]] = prop["__requires"]
+ proptotype[prop["id"]] = tid
+ prop_deps = map(lambda (name, x): (len(x), name), propgraph.items())
+ prop_deps.sort()
+ if follow_types:
+ props_to_create = create_what(prop_deps, propgraph)
+ else:
+ props_to_create = propgraph.keys()
+
+ if debug: print "types", types_to_create
+ if debug: print "-----------------------"
+ if debug: print "props", props_to_create
+
+ base_id, domain_id = s.mqlreadmulti([{"id" : types_to_create[0], "type" : "/type/type", "domain" : {"id" : None}},
+ {"id" : new_location, "a:id" : None}])
+ base_id = base_id["domain"]["id"]
+ domain_id = domain_id["a:id"]
+
+ only_include = types_to_create + props_to_create
+
+ for type in types_to_create:
+ if debug: print type
+ key = ""
+ if len(graph[type]["key"]) == 1:
+ key = graph[type]["key"][0]["value"]
+ else:
+ expectedname = graph[type]["id"].split("/")[-1]
+ if base_id:
+ for group in graph[type]["key"]:
+ if group["namespace"] == base_id:
+ key = group["value"]
+ continue
+ if key is None:
+ key = expectedname
+ tip = None
+ if graph[type]["/freebase/documented_object/tip"]:
+ tip = graph[type]["/freebase/documented_object/tip"]["value"]
+
+ ignore = ("name", "domain", "key", "type", "id", "properties", "/freebase/type_hints/enumeration",
+ "/freebase/type_hints/included_types", "/freebase/type_hints/mediator", "/freebase/documented_object/tip")
+ extra = {}
+ for k, v in graph[type].items():
+ if k not in ignore and not k.startswith("__"):
+ if v:
+ if isinstance(v, basestring):
+ extra.update({k:v})
+ elif isinstance(v, bool):
+ extra.update({k:v})
+ elif v.has_key("id"):
+ extra.update({k:v["id"]})
+ elif v.has_key("value"):
+ extra.update({k:v["value"]})
+ else:
+ raise Exception("There is a problem with getting the property value.")
+
+ create_type(s, graph[type]["name"]["value"], key, domain_id,
+ included=map(lambda x: convert_name(x["id"], base_id, domain_id, only_include), graph[type]["/freebase/type_hints/included_types"]),
+ cvt=graph[type]["/freebase/type_hints/mediator"],
+ tip=tip, extra=extra)
+
+
+ if debug: print "--------------------------"
+
+ for prop in props_to_create:
+ info = graph[proptotype[prop]]["properties"]
+ for i in info:
+ if i["id"] == prop:
+
+ schema = convert_name(proptotype[prop], base_id, domain_id, only_include)
+ if debug: print prop
+ expected = None
+
+ if i["expected_type"]:
+ expected = convert_name(i["expected_type"], base_id, domain_id, only_include)
+ for k in i["key"]:
+ if k.namespace == proptotype[prop]:
+ key = k.value
+ if i["/freebase/documented_object/tip"]:
+ tip = graph[type]["/freebase/documented_object/tip"]
+
+ disambig = i["/freebase/property_hints/disambiguator"]
+
+ ignore = ("name", "expected_type", "key", "id", "master_property", "delegated", "unique", "type", "schema",
+ "/freebase/property_hints/disambiguator", "enumeration", "/freebase/property_hints/enumeration",
+ "/freebase/documented_object/tip")
+ extra = {}
+ for k, v in i.items():
+ if k not in ignore and not k.startswith("__"):
+ if v:
+ if isinstance(v, basestring):
+ extra.update({k:v})
+ elif isinstance(v, bool):
+ extra.update({k:v})
+ elif v.has_key("id"):
+ extra.update({k:v["id"]})
+ elif v.has_key("value"):
+ extra.update({k:v["value"]})
+ else:
+ raise Exception("There is a problem with getting the property value.")
+
+ # since we are creating a property, all these connect insert delicacies are unneccesary
+ """if isinstance(v, basestring) and v.startswith("/"): # an id
+ extra.update({k : {"connect" : "insert", "id" : v}})
+ elif isinstance(v, bool): # a bool value
+ extra.update({k : {"connect" : "insert", "value" : v}})
+ else: # an english value
+ extra.update({k : {"connect" : "insert", "value" : v, "lang" : "/lang/en"}})"""
+
+
+ if i['master_property']:
+ converted_master_property = convert_name(i["master_property"], base_id, domain_id, only_include)
+ if converted_master_property == i["master_property"]:
+ raise Exception("You can't set follow_types to False if there's a cvt. A cvt requires you get all the relevant types. Set follow_types to true.\n" + \
+ "The offending property was %s, whose master was %s." % (prop["id"], prop["master_property"]))
+ reciprocate_property(s, i["name"], key, converted_master_property,
+ i["unique"], disambig=disambig, tip=tip, extra=extra)
+
+ elif i['delegated']:
+ delegate_property(s, convert_name(i['delegated'], base_id, domain_id, only_include), schema,
+ expected=expected, tip=tip, extra=extra)
+
+ else:
+ create_property(s, i["name"], key, schema, expected, i["unique"],
+ disambig=disambig, tip=tip, extra=extra)
+
+
+
+
+
+
+def _get_graph(initial_types, follow_types):
+ """ get the graph of dependencies of all the types involved, starting with a list supplied """
+
+ assert isinstance(initial_types, (list, tuple))
+
+ graph = {}
+ to_update = set(initial_types)
+ done = set()
+ while len(to_update) > 0:
+ new = to_update.pop()
+ graph[new] = _get_needed(s, new)
+ if follow_types:
+ [to_update.add(b) for b in graph[new]["__related"] if b not in done]
+ done.update(graph[new]["__related"])
+ if not follow_types:
+ # we have to check that there are no cvts attached to us, or else
+ # ugly things happen (we can't include the cvt)
+ for prop in graph[new]["properties"]:
+ if prop["master_property"]:
+ raise Exception("You can't set follow_types to False if there's a cvt. A cvt requires you get all the relevant types. Set follow_types to true.\n" + \
+ "The offending property was %s, whose master was %s." % (prop["id"], prop["master_property"]))
+ return graph
+
+"""def create_type_dependencies(s, base_id=None, type_id=None, follow_types=True):
if base_id:
q = {"id" : base_id, "/type/domain/types" : [{"id" : None}] }
@@ -28,18 +227,13 @@ def create_type_dependencies(s, base_id=None, type_id=None):
if not base_id and not type_id:
raise Exception("You need to supply either a base_id or a type_id")
- graph = {}
- to_update = set(types)
- done = set()
- while len(to_update) > 0:
- new = to_update.pop()
- graph[new] = get_needed(s, new)
- [to_update.add(b) for b in graph[new]["related"] if b not in done]
- done.update(graph[new]["related"])
-
+ graph = get_graph(types, follow_types)
+
# find distinct subgraphs (looking at needs)
subgraphs = []
unknown = set(graph.keys())
+ if focus:
+ unknown = set([focus])
while len(unknown) > 0:
visited = set()
to_visit = set([list(unknown)[0]])
@@ -52,8 +246,11 @@ def create_type_dependencies(s, base_id=None, type_id=None):
pass
[to_visit.add(b) for b in graph[new]["related"] if b not in visited]
subgraphs.append(list(visited))
- #pprint(subgraphs)
+
+ print "SUBGRPAHS"
+ pprint(subgraphs)
+ print "GRAPH"
pprint(graph)
return
@@ -79,6 +276,8 @@ def create_type_dependencies(s, base_id=None, type_id=None):
props_to_create = create_what(least_needy, propgraph)
+ # CREATING STUFF
+
domainname = "awesome" + str(int(random.random() * 1e10))
print "\ndomainid", domainname
print "--------------------------"
@@ -142,10 +341,11 @@ def create_type_dependencies(s, base_id=None, type_id=None):
print "\ndomain id was", domainname
-
+"""
+
-def convert_name(old_name, operating_base, new_base):
- if old_name.startswith(operating_base):
+def convert_name(old_name, operating_base, new_base, only_include=None):
+ if old_name in only_include and old_name.startswith(operating_base):
return new_base + old_name.replace(operating_base, "", 1)
else:
return old_name
@@ -171,84 +371,55 @@ def create_what(deps, graph):
-def get_needed(s, type_id):
- #print type_id
- q = {
- "type" : "/type/type",
- "id" : type_id,
- "domain" : [{}],
- "expected_by" : [{}],
- "key" : [{"namespace" : None, "value" : None}],
- "name" : {"value" : None, "lang" : "/lang/en", "optional":True},
- "/freebase/type_hints/included_types" : [{}],
- "/freebase/type_hints/mediator" : None,
- "/freebase/type_hints/enumeration" : None,
- "/freebase/documented_object/tip" : {"value" : None, "limit":1, "optional":True},
- "properties" : [{
- "optional" : True,
- "delegated" : {},
- "enumeration" : None,
- "expected_type" : {},
- "id" : None,
- "key" : [{
- "namespace" : None,
- "value" : None
- }],
- #"link" : [{}],
- "master_property" : {},
- "name" : {"value" : None, "lang" : "/lang/en", "optional":True},
- "reverse_property" : {},
- "schema" : {"id" : None, "name" : None},
- "unique" : None,
- "unit" : None,
- "/freebase/documented_object/tip" : {"value" : None, "limit":1, "optional" : True},
- "/freebase/property_hints/disambiguator" : None
- }]
- }
+def _get_needed(s, type_id):
+ q = TYPE_QUERY
+ q.update(id=type_id)
r = s.mqlread(q)
properties = r.properties
- #print "************************************************" + type_id
- #pprint(r)
- #print "************************************************" + type_id
- # hopefully there's only one domain
- fathers = map(lambda x: x["id"], r["domain"])
+ # let's identify who the parent is in order to only include
+ # other types in that domain. We don't want to go around including
+ # all of commons because someone's a /people/person
+ parents = [r["domain"]["id"]]
- brothers = set()
included_types = map(lambda x: x["id"], r["/freebase/type_hints/included_types"])
- brothers.update(included_types)
+ related_types = set(included_types)
for prop in properties:
if prop["expected_type"]:
- brothers.add(prop["expected_type"]["id"])
-
+ related_types.add(prop["expected_type"])
- family = return_relevant(brothers, fathers)
- needed = return_relevant(included_types, fathers)
+ # we have two different types of relationships: required and related.
+ # related can be used to generate subgraphs of types
+ # required is used to generate the dependency graph of types
+
+ related = return_relevant(related_types, parents)
+ requires = return_relevant(included_types, parents)
# get property information
properties = r["properties"]
for prop in properties:
- needs = set()
+ dependent_on = set()
if prop["master_property"]:
- needs.add(prop["master_property"]["id"])
+ dependent_on.add(prop["master_property"])
if prop["delegated"]:
- needs.add(prop["delegated"]["id"])
+ dependent_on.add(prop["delegated"])
- prop["needs"] = return_relevant(needs, fathers)
+ prop["__requires"] = return_relevant(dependent_on, parents)
- answer = r
- answer.update(related=family, needs=needed, properties=properties)
+ # return all the information along with our special __* properties
+ info = r
+ info.update(__related=related, __requires=requires, __properties=properties)
- return answer
+ return info
-def return_relevant(start_list, fathers):
+def return_relevant(start_list, parents):
final = []
for item in start_list:
indomain = False
- for father in fathers:
- if item.startswith(father):
+ for parent in parents:
+ if item.startswith(parent):
indomain = True
continue
if indomain:
@@ -257,6 +428,21 @@ def return_relevant(start_list, fathers):
if __name__ == '__main__':
- create_type_dependencies(s, base_id="/people")
+ # create domain
+ name = str(int(random.random()*1e10))
+ domain_id = s.create_private_domain("coolcat" + name, "Coolcat" + name)["domain_id"]
+ domain_id = s.mqlread({"id" : domain_id, "a:id" : None})["a:id"]
+ print "domain name", domain_id
+
+ # dump information
+ #graph = dump_type(s, "/user/nitromaster101/coolcat3194242218/bridge_player", follow_types=True)
+ graph = dump_type(s, "/people/person", True)
+
+ # upload it somewhere else
+ upload_type(s, graph, domain_id, debug=True)
+
+
+ print "domain name", domain_id
+ #create_type_dependencies(s, type_id="/base/contractbridge/bridge_player")