diff --git a/etgtools/extractors.py b/etgtools/extractors.py index 4aff5694..af1e9b3c 100644 --- a/etgtools/extractors.py +++ b/etgtools/extractors.py @@ -57,6 +57,9 @@ class BaseDef(object): # class. Should be overridden in derived classes to get what each one # needs in addition to the base. self.name = element.find(self.nameTag).text + if '::' in self.name: + loc = self.name.rfind('::') + self.name = self.name[loc+2:] bd = element.find('briefdescription') if len(bd): self.briefDoc = bd[0] # Should be just one element @@ -470,6 +473,7 @@ class ClassDef(BaseDef): def __init__(self, element=None, kind='class', **kw): super(ClassDef, self).__init__() self.kind = kind + self.protection = '' self.bases = [] # base class names self.includes = [] # .h file for this class self.abstract = False # is it an abstract base class? @@ -482,6 +486,8 @@ class ClassDef(BaseDef): self.convertToPyObject = None self.convertFromPyObject = None self.allowNone = False # Allow the convertFrom code to handle None too. + self.innerclasses = [] + self.isInner = False # Stuff that needs to be generated after the class instead of within # it. Some back-end generators need to put stuff inside the class, and @@ -502,7 +508,23 @@ class ClassDef(BaseDef): self.bases.append(node.text) for node in element.findall('includes'): self.includes.append(node.text) - + + for node in element.findall('innerclass'): + if node.get('prot') == 'private': + continue + from etgtools import XMLSRC + ref = node.get('refid') + fname = os.path.join(XMLSRC, ref+'.xml') + root = et.parse(fname).getroot() + innerclass = root[0] + kind = innerclass.get('kind') + assert kind in ['class', 'struct'] + item = ClassDef(innerclass, kind) + item.protection = node.get('prot') + item.isInner = True + self.innerclasses.append(item) + + # TODO: Is it possible for there to be memberdef's w/o a sectiondef? for node in element.findall('sectiondef/memberdef'): # skip any private items @@ -525,9 +547,9 @@ class ClassDef(BaseDef): else: raise ExtractorError('Unknown memberdef kind: %s' % kind) - # TODO: do we need support for nested classes? - + def _findItems(self): + return self.items + self.innerclasses def addHeaderCode(self, code): diff --git a/etgtools/sip_generator.py b/etgtools/sip_generator.py index 8a68d6d2..9ce42f86 100644 --- a/etgtools/sip_generator.py +++ b/etgtools/sip_generator.py @@ -324,12 +324,18 @@ from %s import * stream.write(nci(c, len(indent2)+4)) stream.write("%s%%End\n" % indent2) - if klass.kind == 'class': - stream.write('\n%spublic:\n' % indent) - # is the generator currently inside the class or after it? klass.generatingInClass = True + + for item in klass.innerclasses: + if klass.kind == 'class': + stream.write('%s%s:\n' % (indent, item.protection)) + item.klass = klass + self.generateClass(item, stream, indent + ' '*4) + if klass.kind == 'class': + stream.write('%spublic:\n' % indent) + # Split the items into public and protected groups ctors = [i for i in klass if isinstance(i, extractors.MethodDef) and @@ -348,8 +354,8 @@ from %s import * extractors.PyMethodDef : self.generatePyMethod, extractors.PyCodeDef : self.generatePyCode, extractors.WigCode : self.generateWigCode, - # TODO: nested classes too? } + for item in ctors: item.klass = klass f = dispatch[item.__class__] @@ -675,13 +681,21 @@ from %s import * prop.klass.generateAfterClass.append(prop) else: klassName = prop.klass.pyName or prop.klass.name - stream.write("%%Extract(id=pycode%s)\n" % self.module_name) - stream.write("_%s_%s = property(%s.%s" % (klassName, prop.name, klassName, prop.getter)) + if '.' in prop.getter: + getter = prop.getter + else: + getter = '%s.%s' % (klassName, prop.getter) if prop.setter: - stream.write(", %s.%s" % (klassName, prop.setter)) + if '.' in prop.setter: + setter = prop.setter + else: + setter = '%s.%s' % (klassName, prop.setter) + + stream.write("%%Extract(id=pycode%s)\n" % self.module_name) + stream.write("%s.%s = property(%s" % (klassName, prop.name, getter)) + if prop.setter: + stream.write(", %s" % setter) stream.write(")\n") - stream.write('%s.%s = _%s_%s\n' % (klassName, prop.name, klassName, prop.name)) - stream.write('del _%s_%s\n' % (klassName, prop.name)) stream.write('%End\n\n') #-----------------------------------------------------------------------