def regularize(node): """? This function ensures that the tree is complete and regular. For example it breaks descriptions into brief and desc tags. """ if microdom.isInstanceOf(node, microdom.MicroDom): if node.tag_ in [TagCtor, TagMethod, TagFunction]: # Add the "decl" tag t = microdom.MicroDom({"tag_": TagDecl}, None, node.name + node.args) node.addChild(t) # Supplement the args tags args = node.args args = args.replace("(", "").replace( ")", "") # remove leading and trailing paren arglst = args.split(',') for arg in arglst: if arg != "void": (typequal, atype, aname) = reargdecl.match(arg).groups() argdefs = node.filterByAttr({AttrName: aname}) if not argdefs: t = microdom.MicroDom( { "tag_": TagParam, AttrType: typequal + atype, AttrName: aname }, None, None) node.addChild(t) for t in argdefs: t.addAttr(AttrType, typequal + atype) for c in node.children_: regularize(c) return node
def createChild(self, parent, childName): name = childName childTag = parent.getElementsByTagName(name) if childTag: childTag = childTag[0] else: childTag = microdom.MicroDom({"tag_":name},[],[]) parent.addChild(childTag) return childTag
def fixupFileDocstring(xml): # This is a docstring that should be associated with the whole file tmp = filter(lambda x: isInstanceOf(x, microdom.MicroDom), xml.children_) if tmp: # If there is ANY documentation at all: t = tmp[0] if int(t.linenum) == 1: #pdb.set_trace() if t.tag_ == "_": (briefText, sp, desc) = t.data_.partition("\n") t.data_ = desc.strip() # if type(t.children_[0]) in StringTypes: # Clean it up in the children list as well # (briefText,sp,desc) = tmp[0].partition("\n") # t.children_[0] = desc.strip() xml.addChild( microdom.MicroDom({"tag_": TagBrief}, [briefText.strip()])) t.reTag(TagDesc) for c in t.children_: # Pull all the tags that shouldn't be in the Desc out of it if isInstanceOf(c, microdom.MicroDom) and c.tag_ in NoDescTags: c.reParent(xml)
def regularize(node, zzdepth=0): """?? This function ensures that the tree is complete and regular. For example it breaks descriptions into brief and desc tags. """ if 0: # Print the nodes try: t = node.pfxsfx() print "**" + (" " * zzdepth) + t[0] except AttributeError: print "**" + str(" " * zzdepth) + str(node) # Regularize the children try: children = node.children_ except AttributeError: children = [] for c in children: regularize(c, zzdepth + 1) # Combine common children (in this case sections with the same name) lkup = {} for c in children: if microdom.isInstanceOf( c, microdom.MicroDom ) and c.tag_ in CombinedTags: # It is a candidate to be merged if lkup.has_key( c.tag_ + c.name): # Yes there is another tag, so it must be merged orig = lkup[c.tag_ + c.name] orig.merge(c) else: lkup[c.tag_ + c.name] = c if microdom.isInstanceOf(node, microdom.MicroDom): # Add an empty "type" attribute if it does not have one if node.tag_ in TypedTags: if not node.attributes_.has_key(AttrType): node.attributes_[AttrType] = "" if node.tag_ in ConstructTags: #print str(node) # Regularize the "brief" and "desc" children if not node.child_.has_key(TagDesc): # Split the children into who should go under the desc and who should go back under me chLst = node.removeChildren() (descChildren, myChildren) = split( lambda x: (not microdom.isInstanceOf(x, microdom.MicroDom)) or (not x.tag_ in NoDescTags), chLst) #descChildren = filter(lambda x: (not microdom.isInstanceOf(x,microdom.MicroDom)) or (not x.tag_ in NoDescTags) ,node.children_) #myChildren = filter(lambda x: not((not microdom.isInstanceOf(x,microdom.MicroDom)) or (not x.tag_ in NoDescTags)) ,node.children_) # Reset me with new children (but all else the same) #node.reset(node.attributes_,myChildren,None,node.parent_) for c in myChildren: node.addChild(c) # Add the Desc tag node.addChild( microdom.MicroDom({"tag_": TagDesc}, descChildren, None, node)) #node.addChild(microdom.MicroDom({"tag_":TagDesc},[],None,node)) if not node.child_.has_key(TagBrief): candidate = node.data_.split("\n")[0].split(". ")[ 0] # Get the first sentence in the first line if candidate: # If there is something then use it as the brief brief = candidate + "..." else: # Or use the 1st sentence of the description brief = node.child_[TagDesc].data_.split(". ")[0] + "..." t = microdom.MicroDom({"tag_": TagBrief}, [brief], None) node.addChild(t) # If there is no "decl" then use the name # TODO: we could search for TagParam children to build the declaration # But really dp.py should generate the decl if node.tag_ in [TagFunction, TagMethod]: if not node.child_.has_key(TagDecl): t = microdom.MicroDom({"tag_": TagDecl}, [node.name], None) node.addChild(t) return node
def recurse(nlst, context=None, forceParentNode=None): for node in nlst: xmlnode = findRelevantTag(xml, node.lineno) #print xmlnode if xmlnode is None: xmlnode = xml # Imports if isInstanceOf(node, ast.ImportFrom): fdxml = xmlnode.findParent(TagFile)[0] fdxml.addChild( microdom.MicroDom( { "tag_": "requires", "module": node.module, "linenum": node.lineno }, [], None)) if isInstanceOf(node, ast.Import): fdxml = xmlnode.findParent(TagFile)[0] for mod in node.names: fdxml.addChild( microdom.MicroDom( { "tag_": "requires", "module": mod.name, "linenum": node.lineno }, [], None)) # Assignment / Variable declaration elif isInstanceOf(node, ast.Assign): if context == TagCtor: varnames = [] for tgt in node.targets: try: varnames.append(tgt.attr) except AttributeError: log.warning("Skipping ctor assignment %s" % str(tgt)) pass else: varnames = [getLvalue(tgt) for tgt in node.targets] if len(varnames) == 1: varnames = varnames[0] # I'm trying to grab the value of an assignment to put into the documentation, i.e. MY_CONST = 50 val = None try: val = node.value.n # for numbers except: pass try: val = node.value.s # for strings except: pass try: val = node.value.id # for names (modules) except: pass if val == None: # But if the assignment is complex, then it does not make any sense to grab it # But maybe you can make sense of these and figure out some cool documentation to add? if isInstanceOf(node.value, ast.Subscript): pass elif isInstanceOf(node.value, ast.Dict): pass elif isInstanceOf(node.value, ast.List): pass elif isInstanceOf(node.value, ast.Call): pass elif isInstanceOf(node.value, ast.Attribute): pass elif isInstanceOf(node.value, ast.BinOp): pass elif isInstanceOf(node.value, ast.IfExp): pass elif isInstanceOf(node.value, ast.Tuple): pass elif isInstanceOf(node.value, ast.Lambda): pass elif isInstanceOf(node.value, ast.ListComp): pass elif isInstanceOf(node.value, ast.Compare): pass else: pdb.set_trace() xmlAttrInsert(xmlnode, { AttrTag: TagVariable, AttrName: varnames, AttrValue: val }) # Function handling elif isInstanceOf(node, ast.FunctionDef): fdxml = xmlnode.findParent(TagFunction) if not fdxml: fdxml = xmlnode else: fdxml = fdxml[0] if node.name == fdxml.attributes_.get( "name", node.name ): # If it HAS a name, its has to be == or I've got the wrong comment # The comments form an XML tree, and the language structure forms a tree as well. # If the language structure's tree should override the XML tree, then forceParentNode # will be true and so this comment will be extracted from its current location and pushed under the forceParentNode # This happens when a class defines its member functions, for example and the user uses ?? instead of correctly matching # xml class scope with the true class scope. if forceParentNode and forceParentNode != fdxml: fdxml.extract() forceParentNode.addChild(fdxml) xmlAttrInsert(fdxml, { AttrTag: TagFunction, AttrName: node.name }) # If its a constructor, hunt thru for member variables if node.name == "__init__": recurse(node.body, TagCtor) # Class handling elif isInstanceOf(node, ast.ClassDef): fdxml = xmlnode.findParent(TagClass) if not fdxml: fdxml = xmlnode else: fdxml = fdxml[0] fp = None # TODO: This class has no documentation, create it based on configuration option if fdxml.tag_ != TagClass and fdxml.tag_ != "_": pass else: xmlAttrInsert(fdxml, { AttrTag: TagClass, AttrName: node.name }) recurse(node.body, TagClass, fdxml) elif isInstanceOf(node, ast.Expr) or isInstanceOf(node, ast.If): pass #- pdb.set_trace() else: log.warning("unrecognised node %s" % str(node))
def updateMicrodom(self): """Write the dynamically changing information back to the loaded microdom tree. The reason I don't create an entirely new tree is to preserve any application extensions that might have been put into the file. """ # First, update the model to make sure that it is internally consistent for (name,i) in self.instances.items(): for parent in filter(lambda ent: isinstance(ent, Entity), i.childOf): # If the object has parent pointers, update them. This is pretty specific to SAFplus data types... fieldName = parent.et.name[0].lower() + parent.et.name[1:] # uncapitalize the first letter to make it use SAFplus bumpycase if i.data.has_key(fieldName): i.data[fieldName] = parent.data["name"] # Locate or create the needed sections in the XML file # find or create the entity area in the microdom entities = self.data.getElementsByTagName("entities") if not entities: entities = microdom.MicroDom({"tag_":"entities"},[],[]) self.data.addChild(entities) else: assert(len(entities)==1) entities = entities[0] # Find or create the GUI area in the microdom. The GUI area is structured like: # ide # ide_entity_info # ide_instance_info ide = self.data.getElementsByTagName("ide") if not ide: ide = microdom.MicroDom({"tag_":"ide"},[],[]) self.data.addChild(ide) else: assert(len(ide)==1) ide = ide[0] ideEntities = ide.getElementsByTagName("ide_entity_info") if not ideEntities: ideEntities = microdom.MicroDom({"tag_":"ide_entity_info"},[],[]) ide.addChild(ideEntities) else: assert(len(ideEntities)==1) ideEntities = ideEntities[0] ideInsts = ide.getElementsByTagName("ide_instance_info") if not ideInsts: ideInsts = microdom.MicroDom({"tag_":"ide_instance_info"},[],[]) ide.addChild(ideInsts) else: assert(len(ideInsts)==1) ideInsts = ideInsts[0] # Write out the entities # iterate through all entities writing them to the microdom, or changing the existing microdom for (name,e) in self.entities.items(): # Find the existing DOM nodes for the entity information, creating the node if it is missing entity = entities.findOneByChild("name",name) if not entity: entity = microdom.MicroDom({"tag_":e.et.name},[],[]) entities.addChild(entity) ideEntity = ideEntities.getElementsByTagName(name) if ideEntity: ideEntity = ideEntity[0] else: ideEntity = microdom.MicroDom({"tag_":name},[],[]) ideEntities.addChild(ideEntity) # Remove all "None", replacing with the default or "" temp = {} for (key,val) in e.data.items(): if val is None: val = e.et.data[key].get("default",None) if val is None: val = "" if val == "None": val = "" temp[key] = val # Write all the data fields into the model's microdom entity.update(temp) # write the IDE specific information to the IDE area of the model xml ideEntity["position"] = str(e.pos) ideEntity["size"] = str(e.size) # Now write all the arrows contains = {} # Create a dictionary to hold all linkages by type for arrow in e.containmentArrows: # Add the contained object to the dictionary keyed off of the object's entitytype tmp = contains.get(arrow.contained.et.name,[]) tmp.append(arrow.contained.data["name"]) contains[arrow.contained.et.name] = tmp # TODO: write the containment arrow IDE specific information to the IDE area of the model xml self.writeContainmentArrow(ideEntity, arrow) # Now erase the missing linkages from the microdom for (key, val) in self.entityTypes.items(): # Look through all the children for a key that corresponds to the name of an entityType (+ s), eg: "ServiceGroups" if not contains.has_key(key): # Element is an entity type but no linkages if entity.child_.has_key(key + 's'): entity.delChild(key + 's') # Ok now write the linkages to the microdom for (key, val) in contains.items(): k = key + "s" if entity.child_.has_key(k): entity.delChild(k) entity.addChild(microdom.MicroDom({"tag_":k},[",".join(val)],"")) # TODO: do we really need to pluralize? Also validate comma separation is ok # Building instance lock fields etType = ide.getElementsByTagName(e.et.name) if not etType: etType = microdom.MicroDom({"tag_":e.et.name},[],[]) ide.addChild(etType) else: assert(len(etType)==1) etType = etType[0] et = etType.getElementsByTagName(name) if not et: et = microdom.MicroDom({"tag_":name},[],[]) etType.addChild(et) else: assert(len(et)==1) et = et[0] et.update(e.instanceLocked) # Find or create the instance area in the microdom instances = self.data.getElementsByTagName("instances") if not instances: instances = microdom.MicroDom({"tag_":"instances"},[],[]) self.data.addChild(instances) else: assert(len(instances)==1) instances = instances[0] # iterate through all instances writing them to the microdom, or changing the existing microdom for (name,e) in self.instances.items(): instance = instances.findOneByChild("name",name) if not instance: instance = microdom.MicroDom({"tag_":e.et.name},[],[]) instances.addChild(instance) # Remove all "None", replacing with the default or "" temp = {} for (key,val) in e.data.items(): if val is None: val = e.et.data[key].get("default",None) if val is None: val = "" if val == "None": val = "" temp[key] = val # Add module and xpath attributes instance.addAttribute("xpath",e.entity.et.data["xpath"] + ("[@name=\"%s\"]" % e.data["name"])) instance.addAttribute("module",e.entity.et.data["module"]) # Write all the data fields into the model's microdom instance.update(temp) # Now write all the arrows contains = {} # Create a dictionary to hold all linkages by type for arrow in e.containmentArrows: # Add the contained object to the dictionary keyed off of the object's entitytype # leaf-list entity type with camelCase(s) key = arrow.contained.et.name[0].lower() + arrow.contained.et.name[1:] + 's' tmp = contains.get(key,[]) tmp.append(arrow.contained.data["name"]) contains[key] = tmp # Now erase the missing linkages from the microdom for (key, val) in self.entityTypes.items(): # Look through all the children for a key that corresponds to the name of an entityType (+ s), eg: "serviceUnits" key = key[0].lower() + key[1:] + 's' if not contains.has_key(key): # Element is an entity type but no linkages if instance.child_.has_key(key): instance.delChild(key) # Ok now write the linkages to the microdom for (key, vals) in contains.items(): if instance.child_.has_key(key): instance.delChild(key) for val in vals: instance.addChild(microdom.MicroDom({"tag_":key},[val],"")) # TODO: do we really need to pluralize? Also validate comma separation is ok # Extra parent entity name entityParentVal = e.entity.data["name"] entityParentKey = "%sType"%e.et.name if instance.child_.has_key(entityParentKey): instance.delChild(entityParentKey) instance.addChild(microdom.MicroDom({"tag_":entityParentKey},[entityParentVal],""))