## Wiki80 is a semantic information network, designed to be used both ## by carbon- and silicon-based life. ## Copyright (C) 2018 Davis Remmel ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . # Instances are literal creations of a type. They are able to set values # to keys defined in their type. They are also able to instead define a # value as a reference to another instance, via the Instance ID (shown # below as 'id_1'. class Instance: # The Definition comes in pre-filled from the Graph class. This is # where this object's properties are stored. definition = None def __init__(self, definition, instances): self.definition = definition self.instances = instances def page_data(self): # This function will render this instance as a jinja-friendly # dict. It gets filled in as a pipeline within this scope. rendered_page = { 'data': {}, # Object data goes here 'sections': {} } # Linkbacks go here # What data types are linked to us? For now, I have these links # pre-defined, but in the future we should crawl the graph to # find them without redundant data. for key in self.definition: value_arr = self.definition[key] # The definition is always an array, but sometimes an array # of one. As in LISP, [None] is equivalent to None. # Go through the definition and see how many are references. # Also, TODO: make this into a map function? for s in value_arr: ret_key = None ret_val = None ret_ref = False place = 'data' if s.startswith('@'): inst = self.instances[s[1:]] ret_key = inst.definition['.type'][0] ret_val = inst.definition['.id'][0] ret_ref = True # If this is a reference, then this is going right # into a section. place = 'sections' else: ret_key = key ret_val = s if place not in rendered_page: rendered_page[place] = {} if ret_key not in rendered_page[place]: rendered_page[place][ret_key] = [] rendered_page[place][ret_key].append({ 'value': ret_val, 'ref': ret_ref }) return rendered_page class Graph: # A Graph2 is only a collection of instances. Right now, this graph # does NOT store connection data; that is stored in the objects # themselves. instances = {} def edit_instance(self, attr): self.instances[attr['.id'][0]] = Instance(attr, self.instances) # Whenever a link is created in the system, we should also # create a linkback. This property could probably be an optional # feature of the system, but it's one I believe important to # experiment with, for it brings with it a system of total # transparency. if '.link' in attr: print attr['.link'] for link in attr['.link']: to_page_id = link[1:] # Strip the '@' to_page_instance = self.get_instance(to_page_id) # TODO: Now we need to add the instance of the CALLING # page to the other one's '.link' list if it is not # already there. This part creates the bi-directional # link. #~ to_page_instance. return self.instances[attr['.id'][0]] def get_instance(self, instance_id): # This method simply returns an instance from the graph. try: instance = self.instances[instance_id] except: # We'll never return _no_ instance -- just blank ones if # they don't exist. The creating page will be added as a # link, and some other information will be provided as # boilerplate (this is something that could alternatively # be done in the view, which I would be a fan of). self.instances[instance_id] = Instance({ '.id': [ instance_id ], '.type': [ 'No Type' ], '.title': [ 'Untitled Page' ], '.wiki_body': [ 'This page has yet to be written.' ], '.link': [ ]}, self.instances) return self.instances[instance_id] return instance def get_types(self): # This function returns an array of all the types in the system # as strings. e.g. ['person', 'device'] for instance in self.instances: print instance return ['device', 'person']