mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-12-16 09:40:07 +01:00
Add ability to generate code into a .py file which does the import of the extension module. This will be used to add Python code to a module so we dont' have to do everything in C++.
git-svn-id: https://svn.wxwidgets.org/svn/wx/sandbox/trunk/Phoenix@66127 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -50,17 +50,34 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
""")
|
||||
if module.name == module.module:
|
||||
stream.write("""
|
||||
%%Module %s.%s
|
||||
%%Module(name=%s.%s, use_argument_names=True)
|
||||
|
||||
%%Copying
|
||||
Copyright: (c) 2010 by Total Control Software
|
||||
Licence: wxWindows license
|
||||
%%End
|
||||
%%RealArgNames
|
||||
|
||||
""" % (module.package, module.name))
|
||||
|
||||
if module.name.startswith('_'):
|
||||
doc = ''
|
||||
if module.docstring:
|
||||
doc = '\n"""\n%s\n"""\n' % module.docstring
|
||||
stream.write("""\
|
||||
%%Extract pycode
|
||||
# This file is generated by wxPython's SIP generator. Do not edit by hand.
|
||||
#
|
||||
# Copyright: (c) 2010 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
%s
|
||||
from %s import *
|
||||
|
||||
%%End
|
||||
|
||||
""" % (doc, module.name))
|
||||
|
||||
else:
|
||||
stream.write("//\n// This file is included from %s.sip\n//\n" % module.module)
|
||||
stream.write("//\n// This file will be included by %s.sip\n//\n" % module.module)
|
||||
|
||||
stream.write(divider)
|
||||
|
||||
@@ -118,6 +135,7 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
extractors.GlobalVarDef : self.generateGlobalVar,
|
||||
extractors.TypedefDef : self.generateTypedef,
|
||||
extractors.WigCode : self.generateWigCode,
|
||||
extractors.PyCodeDef : self.generatePyCode,
|
||||
}
|
||||
|
||||
for item in module:
|
||||
@@ -194,11 +212,21 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
#-----------------------------------------------------------------------
|
||||
def generateWigCode(self, wig, stream, indent=''):
|
||||
assert isinstance(wig, extractors.WigCode)
|
||||
lines = [indent+line for line in wig.code.split('\n')]
|
||||
stream.write('\n'.join(lines))
|
||||
stream.write(nci(wig.code, len(indent), False))
|
||||
stream.write('\n\n')
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
def generatePyCode(self, pc, stream, indent=''):
|
||||
assert isinstance(pc, extractors.PyCodeDef)
|
||||
if hasattr(pc, 'klass') and pc.klass.generatingInClass:
|
||||
pc.klass.generateAfterClass.append(pc)
|
||||
else:
|
||||
stream.write('%Extract pycode\n')
|
||||
stream.write(nci(pc.code, 4))
|
||||
stream.write('\n%End\n\n')
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
def generateClass(self, klass, stream, indent=''):
|
||||
assert isinstance(klass, extractors.ClassDef)
|
||||
@@ -218,6 +246,9 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
stream.write('%s #include <%s>\n' % (indent, inc))
|
||||
stream.write('%s%%End\n' % indent)
|
||||
stream.write('\n%spublic:\n' % indent)
|
||||
|
||||
# is the generator currently inside the class or after it?
|
||||
klass.generatingInClass = True
|
||||
|
||||
# Split the items into public and protected groups
|
||||
ctors = [i for i in klass if
|
||||
@@ -232,6 +263,8 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
extractors.MethodDef : self.generateMethod,
|
||||
extractors.EnumDef : self.generateEnum,
|
||||
extractors.CppMethodDef : self.generateCppMethod,
|
||||
extractors.PyMethodDef : self.generatePyMethod,
|
||||
extractors.PyCodeDef : self.generatePyCode,
|
||||
extractors.WigCode : self.generateWigCode,
|
||||
# TODO: nested classes too?
|
||||
}
|
||||
@@ -250,28 +283,37 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
f(item, stream, indent + ' '*4)
|
||||
|
||||
if klass.convertFromPyObject:
|
||||
stream.write('%s%%ConvertToTypeCode\n' % indent)
|
||||
lines = [indent+l for l in klass.convertFromPyObject.split('\n')]
|
||||
stream.write('\n'.join(lines))
|
||||
stream.write('%s%%End\n' % indent)
|
||||
self.generateConvertCode('%ConvertToTypeCode',
|
||||
klass.convertFromPyObject,
|
||||
stream, indent + ' '*4)
|
||||
|
||||
if klass.convertToPyObject:
|
||||
stream.write('%s%%ConvertFromTypeCode\n' % indent)
|
||||
lines = [indent+l for l in klass.convertToPyObject.split('\n')]
|
||||
stream.write('\n'.join(lines))
|
||||
stream.write('%s%%End\n' % indent)
|
||||
self.generateConvertCode('%ConvertFromTypeCode',
|
||||
klass.convertToPyObject,
|
||||
stream, indent + ' '*4)
|
||||
|
||||
stream.write('%s}; // end of class %s\n\n\n' % (indent, klass.name))
|
||||
|
||||
# Now generate anything that was deferred until after the class is finished
|
||||
klass.generatingInClass = False
|
||||
for item in klass.generateAfterClass:
|
||||
f = dispatch[item.__class__]
|
||||
f(item, stream, indent)
|
||||
|
||||
|
||||
|
||||
def generateConvertCode(self, kind, code, stream, indent):
|
||||
stream.write('%s%s\n' % (indent, kind))
|
||||
stream.write(nci(code, len(indent)+4))
|
||||
stream.write('%s%%End\n' % indent)
|
||||
|
||||
|
||||
|
||||
def generateMemberVar(self, memberVar, stream, indent):
|
||||
assert isinstance(memberVar, extractors.MemberVarDef)
|
||||
if memberVar.ignored:
|
||||
return
|
||||
stream.write('%s%s %s' % (indent, memberVar.type, memberVar.name))
|
||||
stream.write('%s;\n' % self.annotate(memberVar))
|
||||
stream.write('%s;\n\n' % self.annotate(memberVar))
|
||||
|
||||
|
||||
def generateProperty(self, prop, stream, indent):
|
||||
@@ -320,12 +362,24 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
(indent, method.type, method.name, method.argsString,
|
||||
self.annotate(method)))
|
||||
stream.write('%s%%MethodCode\n' % indent)
|
||||
lines = [indent+l for l in method.body.split('\n')]
|
||||
stream.write('\n'.join(lines))
|
||||
if len(lines) == 1:
|
||||
stream.write('\n%s' % indent)
|
||||
stream.write('%End\n\n')
|
||||
stream.write(nci(method.body, len(indent)+4))
|
||||
stream.write('%s%%End\n\n' % indent)
|
||||
|
||||
|
||||
def generatePyMethod(self, pm, stream, indent):
|
||||
assert isinstance(pm, extractors.PyMethodDef)
|
||||
if pm.klass.generatingInClass:
|
||||
pm.klass.generateAfterClass.append(pm)
|
||||
else:
|
||||
klassName = pm.klass.pyName or pm.klass.name
|
||||
stream.write("%Extract pycode\n")
|
||||
stream.write("def _%s_%s%s:\n" % (klassName, pm.name, pm.argsString))
|
||||
if pm.briefDoc:
|
||||
stream.write(nci('"""\n%s\n"""\n' % pm.briefDoc, 4))
|
||||
stream.write(nci(pm.body, 4))
|
||||
stream.write('%s.%s = _%s_%s\n' % (klassName, pm.name, klassName, pm.name))
|
||||
stream.write('\n%End\n\n')
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
def annotate(self, item):
|
||||
@@ -383,3 +437,48 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase):
|
||||
return ''
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# helpers and utilities
|
||||
|
||||
def nci(text, numSpaces=0, stripLeading=True):
|
||||
"""
|
||||
Normalize Code Indents
|
||||
|
||||
First use the count of leading spaces on the first line and remove that
|
||||
many spaces from the front of all lines, and then indent each line by
|
||||
adding numSpaces spaces. This is used so we can convert the arbitrary
|
||||
indents that might be used by the treaker code into what is expected for
|
||||
the context we are generating for.
|
||||
"""
|
||||
def _getLeadingSpaceCount(line):
|
||||
count = 0
|
||||
for c in line:
|
||||
assert c != '\t', "Use spaces for indent, not tabs"
|
||||
if c != ' ':
|
||||
break
|
||||
count += 1
|
||||
else:
|
||||
assert False, "First line should not be empty."
|
||||
return count
|
||||
|
||||
def _allSpaces(text):
|
||||
for c in text:
|
||||
if c != ' ':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
lines = text.rstrip().split('\n')
|
||||
if stripLeading:
|
||||
numStrip = _getLeadingSpaceCount(lines[0])
|
||||
else:
|
||||
numStrip = 0
|
||||
|
||||
for idx, line in enumerate(lines):
|
||||
assert _allSpaces(line[:numStrip]), "Indentation inconsistent with first line"
|
||||
lines[idx] = ' '*numSpaces + line[numStrip:]
|
||||
|
||||
newText = '\n'.join(lines) + '\n'
|
||||
return newText
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user