def __init__(self): self._fp = None # parse the defs file self.parser = defsparser.DefsParser(()) self.overrides = override.Overrides() self.classmap = {} self.docs = {}
def generate(filename, outfile=None, overridesfile=None): # parse the file all_elements = parse(filename) def resolve(val, attr): """Resolve references. """ try: refs = val.references[attr] except KeyError: val.references[attr] = None return if type(refs) is type([]): unrefs = [] for r in refs: unrefs.append(all_elements[r]) val.references[attr] = unrefs else: val.references[attr] = all_elements[refs] overrides = override.Overrides(overridesfile) writer = Writer(outfile, overrides) # extract usable elements from all_elements. Some elements are given # some extra attributes. classes = { } enumerations = { } generalizations = { } associations = { } properties = { } operations = { } extensions = { } # for identifying metaclasses for key, val in all_elements.items(): # Find classes, *Kind (enumerations) are given special treatment if isinstance(val, element): if val.type == 'Class' and val.get('name'): if val['name'].endswith('Kind') or val['name'].endswith('Sort'): enumerations[key] = val else: # Metaclasses are removed later on (need to be checked # via the Extension instances) classes[key] = val # Add extra properties for easy code generation: val.specialization = [] val.generalization = [] val.stereotypeName = None val.written = False elif val.type == 'Generalization': generalizations[key] = val elif val.type == 'Association': val.asAttribute = None associations[key] = val elif val.type == 'Property': properties[key] = val #resolve(val, 'typeValue') #resolve(val, 'defaultValue') #resolve(val, 'lowerValue') #resolve(val, 'upperValue') resolve(val, 'appliedStereotype') for st in val.appliedStereotype or []: resolve(st, 'slot') for slot in st.slot or []: resolve(slot, 'value') resolve(slot, 'definingFeature') val.written = False elif val.type == 'Operation': operations[key] = val elif val.type == 'Extension': extensions[key] = val # find inheritance relationships for g in generalizations.values(): #assert g.specific and g.general specific = g['specific'] general = g['general'] classes[specific].generalization.append(classes[general]) classes[general].specialization.append(classes[specific]) # add values to enumerations: for e in enumerations.values(): values = [] for key in e['ownedAttribute']: values.append(str(properties[key]['name'])) e.enumerates = tuple(values) # Remove metaclasses from classes dict # should check for Extension.memberEnd<Property>.type for e in extensions.values(): ends = [] for end in e.memberEnd: end = all_elements[end] if not end['type']: continue end.type = all_elements[end['type']] ends.append(end) e.memberEnd = ends if ends: del classes[e.memberEnd[0].type.id] # create file header writer.write(header) # Tag classes with appliedStereotype for c in classes.values(): if c.get('appliedStereotype'): # Figure out stereotype name through # Class.appliedStereotype.classifier.name instSpec = all_elements[c.appliedStereotype[0]] sType = all_elements[instSpec.classifier[0]] c.stereotypeName = sType.name print " class '%s' has been stereotyped as '%s'" % (c.name, c.stereotypeName) writer.write("# class '%s' has been stereotyped as '%s'\n" % (c.name, c.stereotypeName)) #c.written = True def tag_children(me): for child in me.specialization: child.stereotypeName = sType.name print " class '%s' has been stereotyped as '%s' too" % (child.name, child.stereotypeName) writer.write("# class '%s' has been stereotyped as '%s' too\n" % (child.name, child.stereotypeName)) #child.written = True tag_children(child) tag_children(c) ignored_classes = set() # create class definitions, not for SimpleAttribute for c in classes.values(): if c.stereotypeName == 'SimpleAttribute': ignored_classes.add(c) else: writer.write_classdef(c) # create attributes and enumerations derivedattributes = { } for c in filter(lambda c: c not in ignored_classes, classes.values()): for p in c.get('ownedAttribute') or []: a = properties.get(p) # set class_name, since write_attribute depends on it a.class_name = c['name'] if not a.get('association'): if overrides.derives('%s.%s' % (a.class_name, a.name)): derivedattributes[a.name] = a else: writer.write_attribute(a, enumerations) # create associations, derivedunions are held back derivedunions = { } # indexed by name in stead of id redefines = [ ] for a in associations.values(): ends = [] # Resolve some properties: for end in a.memberEnd: end = properties[end] end.type = classes[end['type']] end.class_ = end.get('class_') and classes[end['class_']] or None end.is_simple_attribute = False if end.type and end.type.stereotypeName == 'SimpleAttribute': end.is_simple_attribute = True a.asAttribute = end ends.append(end) for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])): parse_association_end(e1, e2) for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])): if a.asAttribute: if a.asAttribute is e1 and e1.navigable: writer.write("# '%s.%s' is a simple attribute\n" % (e2.type.name, e1.name)) e1.class_name = e2.type.name e1.typeValue = 'str' writer.write_attribute(e1, enumerations) e1.written = True e2.written = True elif e1.redefines: redefines.append(e1) elif e1.derived or overrides.derives('%s.%s' % (e1.class_name, e1.name)): assert not derivedunions.get(e1.name), "%s.%s is already in derived union set in class %s" % (e1.class_name, e1.name, derivedunions.get(e1.name).class_name) derivedunions[e1.name] = e1 e1.union = [ ] e1.written = False elif e1.navigable: writer.write_association(e1, e2) # create derived unions, first link the association ends to the d for a in (v for v in properties.values() if v.subsets): for s in a.subsets or (): try: if a.type not in ignored_classes: derivedunions[s].union.append(a) except KeyError: msg('not a derived union: %s.%s' % (a.class_name, s)) # TODO: We should do something smart here, since derived attributes (mostly) # may depend on other derived attributes or associations. for d in derivedattributes.values(): writer.write_attribute(d) for d in derivedunions.values(): writer.write_derivedunion(d) for r in redefines or (): msg('redefining %s -> %s.%s' % (r.redefines, r.class_name, r.name)) writer.write_redefine(r) # create operations for c in filter(lambda c: c not in ignored_classes, classes.values()): for p in c.get('ownedOperation') or (): o = operations.get(p) o.class_name = c['name'] writer.write_operation(o) writer.close()
docs = docextract.extract(doc_dirs) p = defsparser.DefsParser(defs_file) p.startParsing() # create list of class c_class_list = [] for obj in p.objects: c_class_list.append(get_c_name(obj.c_name)) add_override_methods(p) f = file(wrap_file) wrap_file_cont = f.read() override_file_cont = "" override = override.Overrides() #enums """ for enum in p.enums: if docs.has_key(enum.c_name): print "\"\"\"" printdoc(docs[enum.c_name].description) print "\"\"\"" for i in range(len(enum.values)-1): print enum.values[i][1].replace("GWY_", ""), ',', print enum.values[len(enum.values)-1][1].replace("GWY_", ""), " = range(", len(enum.values), ")" """ # Keep GENERATED seprarated so that this file is not marked generated. print "# This is dummy " + "GENERATED" + " file used for generation of documentation"