diff --git a/pyste/TODO b/pyste/TODO index de588b14..f9a54bbe 100644 --- a/pyste/TODO +++ b/pyste/TODO @@ -8,3 +8,6 @@ instance) - Virtual operators + + +- staticmethod bug diff --git a/pyste/src/Pyste/Exporter.py b/pyste/src/Pyste/Exporter.py index f37ed21e..ff28ecef 100644 --- a/pyste/src/Pyste/Exporter.py +++ b/pyste/src/Pyste/Exporter.py @@ -11,6 +11,7 @@ class Exporter: def __init__(self, info, parser_tail=None): self.info = info self.parser_tail = parser_tail + self.interface_file = None def Name(self): diff --git a/pyste/src/Pyste/HeaderExporter.py b/pyste/src/Pyste/HeaderExporter.py index f86508c3..89fe1ed3 100644 --- a/pyste/src/Pyste/HeaderExporter.py +++ b/pyste/src/Pyste/HeaderExporter.py @@ -64,7 +64,7 @@ class HeaderExporter(Exporter): exporter = exporter_type(info) exporter.SetDeclarations(self.declarations) exporter.SetParsedHeader(self.parser_header) - codeunit.SetCurrent(exporter.Unit()) + codeunit.SetCurrent(self.interface_file, exporter.Unit()) exporter.GenerateCode(codeunit, exported_names) diff --git a/pyste/src/Pyste/MultipleCodeUnit.py b/pyste/src/Pyste/MultipleCodeUnit.py index ca4528b9..57e25f14 100644 --- a/pyste/src/Pyste/MultipleCodeUnit.py +++ b/pyste/src/Pyste/MultipleCodeUnit.py @@ -16,37 +16,40 @@ class MultipleCodeUnit(object): def __init__(self, modulename, outdir): self.modulename = modulename self.outdir = outdir - self.codeunits = {} # maps from a header to a SingleCodeUnit + self.codeunits = {} # maps from a (filename, function) to a SingleCodeUnit self.functions = [] self._current = None + self.all = SingleCodeUnit(None, None) - def _FunctionName(self, code_unit_name): - return '_Export_%s' % utils.makeid(code_unit_name) + def _FunctionName(self, export_name): + return 'Export_%s' % utils.makeid(export_name) - def _FileName(self, code_unit_name): - filename = os.path.basename(code_unit_name) + def _FileName(self, interface_file): + filename = os.path.basename(interface_file) filename = '_%s.cpp' % os.path.splitext(filename)[0] return os.path.join(self.outdir, filename) - def SetCurrent(self, code_unit_name): + def SetCurrent(self, interface_file, export_name): 'Changes the current code unit' - try: - if code_unit_name is not None: - codeunit = self.codeunits[code_unit_name] - else: - codeunit = None - except KeyError: - filename = self._FileName(code_unit_name) - function_name = self._FunctionName(code_unit_name) - codeunit = SingleCodeUnit(None, filename) - codeunit.module_definition = 'void %s()' % function_name - self.codeunits[code_unit_name] = codeunit - if code_unit_name != '__all__': - self.functions.append(function_name) - self._current = codeunit + if export_name is None: + self._current = None + elif export_name is '__all__': + self._current = self.all + else: + filename = self._FileName(interface_file) + function = self._FunctionName(export_name) + try: + codeunit = self.codeunits[(filename, function)] + except KeyError: + codeunit = SingleCodeUnit(None, filename) + codeunit.module_definition = 'void %s()' % function + self.codeunits[(filename, function)] = codeunit + if function not in self.functions: + self.functions.append(function) + self._current = codeunit def Current(self): @@ -74,16 +77,31 @@ class MultipleCodeUnit(object): def Save(self): # create the directory where all the files will go self._CreateOutputDir(); + # order all code units by filename, and merge them all + codeunits = {} # filename => list of codeunits + # the main_unit holds all the include, declaration and declaration-outside sections + # to keep them all in the top of the source file + main_unit = None + for (filename, _), codeunit in self.codeunits.items(): + if filename not in codeunits: + codeunits[filename] = [codeunit] + main_unit = codeunit + main_unit.Merge(self.all) + else: + for section in ('include', 'declaration', 'declaration-outside'): + main_unit.code[section] = main_unit.code[section] + codeunit.code[section] + codeunit.code[section] = '' + codeunits[filename].append(codeunit) # write all the codeunits, merging first the contents of # the special code unit named __all__ - __all__ = self.codeunits.get('__all__') - for name, codeunit in self.codeunits.items(): - if name != '__all__': - if __all__: - codeunit.Merge(__all__) - codeunit.Save() + for codeunits in codeunits.values(): + append = False + for codeunit in codeunits: + codeunit.Save(append) + if not append: + append = True # generate the main cpp - filename = os.path.join(self.outdir, self.modulename + '.cpp') + filename = os.path.join(self.outdir, '_main.cpp') fout = SmartFile(filename, 'w') fout.write(utils.left_equals('Include')) fout.write('#include \n\n') diff --git a/pyste/src/Pyste/SingleCodeUnit.py b/pyste/src/Pyste/SingleCodeUnit.py index 6f3fc2f6..f86cdc09 100644 --- a/pyste/src/Pyste/SingleCodeUnit.py +++ b/pyste/src/Pyste/SingleCodeUnit.py @@ -23,7 +23,7 @@ class SingleCodeUnit: # define the avaiable sections self.code = {} # include section - self.code['include'] = '' + self.code['include'] = '#include \n' # declaration section (inside namespace) self.code['declaration'] = '' # declaration (outside namespace) @@ -58,18 +58,22 @@ class SingleCodeUnit: pass - def Save(self): + def Save(self, append=False): 'Writes this code unit to the filename' space = '\n\n' - fout = SmartFile(self.filename, 'w') + if not append: + flag = 'w' + else: + flag = 'a' + fout = SmartFile(self.filename, flag) # includes - includes = remove_duplicated_lines(self.code['include']) - fout.write('\n' + left_equals('Includes')) - fout.write('#include \n') - fout.write(includes) - fout.write(space) + if self.code['include']: + includes = remove_duplicated_lines(self.code['include']) + fout.write('\n' + left_equals('Includes')) + fout.write(includes) + fout.write(space) # using - if settings.USING_BOOST_NS: + if settings.USING_BOOST_NS and not append: fout.write(left_equals('Using')) fout.write('using namespace boost::python;\n\n') # declarations @@ -77,7 +81,8 @@ class SingleCodeUnit: declaration_outside = self.code['declaration-outside'] if declaration_outside or declaration: fout.write(left_equals('Declarations')) - fout.write(declaration_outside + '\n\n') + if declaration_outside: + fout.write(declaration_outside + '\n\n') if declaration: pyste_namespace = namespaces.pyste[:-2] fout.write('namespace %s {\n\n\n' % pyste_namespace) diff --git a/pyste/src/Pyste/exporters.py b/pyste/src/Pyste/exporters.py index 65536780..56018fb5 100644 --- a/pyste/src/Pyste/exporters.py +++ b/pyste/src/Pyste/exporters.py @@ -1,3 +1,5 @@ # a list of Exporter instances exporters = [] + +current_interface = None # the current interface file being processed diff --git a/pyste/src/Pyste/infos.py b/pyste/src/Pyste/infos.py index 46113cbe..a7d644a6 100644 --- a/pyste/src/Pyste/infos.py +++ b/pyste/src/Pyste/infos.py @@ -59,6 +59,7 @@ class FunctionInfo(DeclarationInfo): # create a FunctionExporter exporter = FunctionExporter(InfoWrapper(self), tail) exporters.exporters.append(exporter) + exporter.interface_file = exporters.current_interface #============================================================================== @@ -74,6 +75,7 @@ class ClassInfo(DeclarationInfo): # create a ClassExporter exporter = ClassExporter(InfoWrapper(self), tail) exporters.exporters.append(exporter) + exporter.interface_file = exporters.current_interface #============================================================================== @@ -86,6 +88,7 @@ class IncludeInfo(DeclarationInfo): self._Attribute('include', include) exporter = IncludeExporter(InfoWrapper(self)) exporters.exporters.append(exporter) + exporter.interface_file = exporters.current_interface #============================================================================== @@ -135,6 +138,7 @@ class EnumInfo(DeclarationInfo): self._Attribute('exclude', False) exporter = EnumExporter(InfoWrapper(self)) exporters.exporters.append(exporter) + exporter.interface_file = exporters.current_interface #============================================================================== @@ -147,6 +151,7 @@ class HeaderInfo(DeclarationInfo): self._Attribute('include', include) exporter = HeaderExporter(InfoWrapper(self)) exporters.exporters.append(exporter) + exporter.interface_file = exporters.current_interface #============================================================================== @@ -160,6 +165,7 @@ class VarInfo(DeclarationInfo): self._Attribute('include', include) exporter = VarExporter(InfoWrapper(self)) exporters.exporters.append(exporter) + exporter.interface_file = exporters.current_interface #============================================================================== diff --git a/pyste/src/Pyste/pyste.py b/pyste/src/Pyste/pyste.py index 6adb4492..2b4b38fd 100644 --- a/pyste/src/Pyste/pyste.py +++ b/pyste/src/Pyste/pyste.py @@ -158,6 +158,7 @@ def Begin(): includes, defines, module, out, interfaces, multiple = ParseArguments() # execute the interface files for interface in interfaces: + exporters.current_interface = interface context = CreateContext() execfile(interface, context) # create the parser @@ -211,7 +212,7 @@ def Begin(): exported_names = {} for export in exports: if multiple: - codeunit.SetCurrent(export.Unit()) + codeunit.SetCurrent(export.interface_file, export.Unit()) export.GenerateCode(codeunit, exported_names) exported_names[export.Name()] = 1 # force collect of cyclic references