| # Copyright Bruno da Silva de Oliveira 2003. Use, modification and |
| # distribution is subject to the Boost Software License, Version 1.0. |
| # (See accompanying file LICENSE_1_0.txt or copy at |
| # http://www.boost.org/LICENSE_1_0.txt) |
| |
| from SingleCodeUnit import SingleCodeUnit |
| import os |
| import utils |
| from SmartFile import SmartFile |
| |
| |
| #============================================================================== |
| # MultipleCodeUnit |
| #============================================================================== |
| class MultipleCodeUnit(object): |
| ''' |
| Represents a bunch of cpp files, where each cpp file represents a header |
| to be exported by pyste. Another cpp, named <module>.cpp is created too. |
| ''' |
| |
| def __init__(self, modulename, outdir): |
| self.modulename = modulename |
| self.outdir = outdir |
| self.codeunits = {} # maps from a (filename, function) to a SingleCodeUnit |
| self.functions = [] |
| self._current = None |
| self.all = SingleCodeUnit(None, None) |
| |
| |
| def _FunctionName(self, interface_file): |
| name = os.path.splitext(interface_file)[0] |
| return 'Export_%s' % utils.makeid(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, interface_file, export_name): |
| 'Changes the current code unit' |
| 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(interface_file) |
| try: |
| codeunit = self.codeunits[filename] |
| except KeyError: |
| codeunit = SingleCodeUnit(None, filename) |
| codeunit.module_definition = 'void %s()' % function |
| self.codeunits[filename] = codeunit |
| if function not in self.functions: |
| self.functions.append(function) |
| self._current = codeunit |
| |
| |
| def Current(self): |
| return self._current |
| |
| current = property(Current, SetCurrent) |
| |
| |
| def Write(self, section, code): |
| if self._current is not None: |
| self.current.Write(section, code) |
| |
| |
| def Section(self, section): |
| if self._current is not None: |
| return self.current.Section(section) |
| |
| |
| def _CreateOutputDir(self): |
| try: |
| os.mkdir(self.outdir) |
| except OSError: pass # already created |
| |
| |
| 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 |
| |
| # While ordering all code units by file name, the first code |
| # unit in the list of code units is used as the main unit |
| # which dumps all the include, declaration and |
| # declaration-outside sections at the top of the file. |
| for filename, codeunit in self.codeunits.items(): |
| if filename not in codeunits: |
| # this codeunit is the main codeunit. |
| codeunits[filename] = [codeunit] |
| codeunit.Merge(self.all) |
| else: |
| main_unit = codeunits[filename][0] |
| 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) |
| |
| # Now write all the codeunits appending them correctly. |
| for file_units in codeunits.values(): |
| append = False |
| for codeunit in file_units: |
| codeunit.Save(append) |
| if not append: |
| append = True |
| |
| |
| def GenerateMain(self, interfaces): |
| # generate the main cpp |
| filename = os.path.join(self.outdir, '_main.cpp') |
| fout = SmartFile(filename, 'w') |
| fout.write(utils.left_equals('Include')) |
| fout.write('#include <boost/python/module.hpp>\n\n') |
| fout.write(utils.left_equals('Exports')) |
| functions = [self._FunctionName(x) for x in interfaces] |
| for function in functions: |
| fout.write('void %s();\n' % function) |
| fout.write('\n') |
| fout.write(utils.left_equals('Module')) |
| fout.write('BOOST_PYTHON_MODULE(%s)\n' % self.modulename) |
| fout.write('{\n') |
| indent = ' ' * 4 |
| for function in functions: |
| fout.write(indent) |
| fout.write('%s();\n' % function) |
| fout.write('}\n') |
| |
| |
| |