import os, sys from . import format from bazbase import structure, custom root = None path_for_element = {} parent_for_element = {} children_for_element = {} undug_elements = [] class parent_handler(object): def start_element(self,e,parent=None): pass def end_element(self, e): pass def prop(self, e, p, contents): if p == u'parent': parent_for_element[e] = contents else: pass def dig_element_helper(nexte): nextpath = os.path.dirname(path_for_element[nexte]) # Could already be there because of toplevels if nexte not in children_for_element: children_for_element[nexte] = [] for d in os.listdir(os.path.join(root, nextpath)): if d.endswith('.yaml') and d != '%s.yaml' % nexte: kid = d[:-len('.yaml')] path_for_element[kid] = '%s/%s.yaml' % (nextpath, kid) parent_for_element[kid] = nexte children_for_element[kid] = () children_for_element[nexte].append(kid) elif os.path.exists(os.path.join(root, nextpath, d, '%s.yaml' % d)): path_for_element[d] = '%s/%s/%s.yaml' % (nextpath, d, d) parent_for_element[d] = nexte children_for_element[nexte].append(d) undug_elements.append(d) def dig_until_element(ename): if not path_for_element: for d in os.listdir(root): path = '%s/%s.yaml' % (d, d) if os.path.exists(os.path.join(root, path)): path_for_element[d] = path if d == 'Object': parent_for_element[d] = None else: format.parse(os.path.join(root, path), parent_handler()) undug_elements.append(d) while undug_elements and (ename is None or ename not in path_for_element): nexte = undug_elements.pop(0) dig_element_helper(nexte) def dig_element(ename): assert path_for_element if ename in undug_elements: undug_elements.remove(ename) dig_element_helper(ename) else: assert ename in path_for_element assert ename in children_for_element, ename def dig_completely(): dig_until_element(None) class value_map_handler(object): def __init__(self, od, elm): self.elm = elm self.od = od def start_element(self,e,parent=None): pass def end_element(self, e): pass def prop(self, e, p, contents): if p == u'parent': pass else: if isinstance(contents, format.Include): fmt = contents.ext contents = contents.val else: contents = contents.encode('utf-8') fmt = 'creole' self.od[p] = structure.Propval(self.elm, p, contents, fmt) def get_include(self, path): with file(os.path.join(root, os.path.dirname(self.elm._path), path)) as fil: return fil.read() class YamlElement(structure.Element): __slots__ = ('_path',) def __init__(self, path): assert path.endswith('.yaml'), path assert not path.startswith('/') ename = unicode(os.path.basename(path[:-len('.yaml')]), 'utf-8') structure.Element.__init__(self, ename) self._path = path #def set_prop(self, propname, value): # self._e[propname] = value def get_descendants(self): ret = [] kids = get_children(self.ename, self) for k in kids: ret.append(k) ret += k.get_descendants() return ret def is_ancestor_of(self, other): return self in other.get_ancestors() def get_ancestors(self): ret = [] e = self.get_parent() while e is not None: ret.insert(0, e) e = e.get_parent() return ret #def create_child(self, ename): # return YamlElement(model.Element(ename, self._e)) def _get_value_map_impl(self, od): format.parse(os.path.join(root, self._path), value_map_handler(od, self)) parent = self.get_parent() if parent is not None: vm = parent.get_value_map() for pname in vm: if pname not in od: od[pname] = structure.Propval( self, pname, structure.get_prop(pname).default, 'creole') #def set_parent(self, parent): # self._e.parent = parent._e def get_root_element(): return YamlElement('Object/Object.yaml') #def create_root_element(ename): # return YamlElement(model.Element(ename, parent=None)) class prop_handler(object): def __init__(self, attrs): self.attrs = attrs def start_element(self,e,parent=None): pass def end_element(self, e): pass def prop(self, p, a, contents): self.attrs[a] = format.interpret_as_prop(a, contents) class YamlProp(structure.Prop): __slots__ = () def __init__(self, pname): attrs = {} format.parse(os.path.join(root, 'props/%s.yaml' % pname), prop_handler(attrs)) # TODO(xavid): centralize this defaulting with model if u'flavor' not in attrs: attrs[u'flavor'] = custom.DEFAULT_FLAVOR if u'default' not in attrs: attrs[u'default'] = structure.PARENT_DOT_THIS if u'visible' not in attrs: attrs[u'visible'] = False if u'comment' not in attrs: attrs[u'comment'] = u'' structure.Prop.__init__(self, pname, attrs[u'flavor'], attrs[u'default'], attrs[u'visible'], attrs[u'comment']) #def set_flavor(self, flavor): # self._p.flavor = flavor # self._flavor = flavor #def set_default(self, default): # self._p.default = default # self._default = default #def set_visible(self, visible): # self._p.visible = visible # self._visibile = visible #def set_comment(self, comment): # self._p.comment = comment # self._comment = comment # Should be ordered such that each element is followed by a single # region consisting of any included descendants. Because of prop # inheritance, there shouldn't be holes. #def containing_elements(self): # return [YamlElement(e) # for e in model.Element.query.join(model.Element.propvals) # .filter(model.Propval.prop_id == self._p.id) # .order_by(model.Element.treeleft).all()] def list_all_props(): return [YamlProp(p[:-len('.yaml')]) for p in os.listdir(os.path.join(root, 'props')) if p.endswith('yaml')] def list_all_elements(): dig_completely() return [YamlElement(path_for_element[ename]) for ename in path_for_element] def get_element(ename): dig_until_element(ename) if ename in path_for_element: return YamlElement(path_for_element[ename]) else: return None def get_prop(pname): if os.path.exists('props/%s.yaml' % pname): return YamlProp(pname) else: return None #def create_prop(pname, flavor=None): # return YamlProp(model.Prop(pname, flavor)) def get_parent(ename, e): dig_until_element(ename) p = parent_for_element[ename] if p is None: # Object return None else: assert p != ename, (p, ename) dig_until_element(p) assert p in path_for_element, (p, path_for_element) return YamlElement(path_for_element[p]) def get_children(ename, e): dig_until_element(ename) dig_element(ename) return [YamlElement(path_for_element[d]) for d in children_for_element[ename]] # Overall operations #def clear_database(): # model.clear() def flush_database_for_test(): pass #def verify_tree_for_test(): # model.verifyTree()