1 | # Copyright Bruno da Silva de Oliveira 2003. Use, modification and |
---|
2 | # distribution is subject to the Boost Software License, Version 1.0. |
---|
3 | # (See accompanying file LICENSE_1_0.txt or copy at |
---|
4 | # http:#www.boost.org/LICENSE_1_0.txt) |
---|
5 | |
---|
6 | from SingleCodeUnit import SingleCodeUnit |
---|
7 | import os |
---|
8 | import utils |
---|
9 | from SmartFile import SmartFile |
---|
10 | |
---|
11 | |
---|
12 | #============================================================================== |
---|
13 | # MultipleCodeUnit |
---|
14 | #============================================================================== |
---|
15 | class MultipleCodeUnit(object): |
---|
16 | ''' |
---|
17 | Represents a bunch of cpp files, where each cpp file represents a header |
---|
18 | to be exported by pyste. Another cpp, named <module>.cpp is created too. |
---|
19 | ''' |
---|
20 | |
---|
21 | def __init__(self, modulename, outdir): |
---|
22 | self.modulename = modulename |
---|
23 | self.outdir = outdir |
---|
24 | self.codeunits = {} # maps from a (filename, function) to a SingleCodeUnit |
---|
25 | self.functions = [] |
---|
26 | self._current = None |
---|
27 | self.all = SingleCodeUnit(None, None) |
---|
28 | |
---|
29 | |
---|
30 | def _FunctionName(self, interface_file): |
---|
31 | name = os.path.splitext(interface_file)[0] |
---|
32 | return 'Export_%s' % utils.makeid(name) |
---|
33 | |
---|
34 | |
---|
35 | def _FileName(self, interface_file): |
---|
36 | filename = os.path.basename(interface_file) |
---|
37 | filename = '_%s.cpp' % os.path.splitext(filename)[0] |
---|
38 | return os.path.join(self.outdir, filename) |
---|
39 | |
---|
40 | |
---|
41 | def SetCurrent(self, interface_file, export_name): |
---|
42 | 'Changes the current code unit' |
---|
43 | if export_name is None: |
---|
44 | self._current = None |
---|
45 | elif export_name is '__all__': |
---|
46 | self._current = self.all |
---|
47 | else: |
---|
48 | filename = self._FileName(interface_file) |
---|
49 | function = self._FunctionName(interface_file) |
---|
50 | try: |
---|
51 | codeunit = self.codeunits[filename] |
---|
52 | except KeyError: |
---|
53 | codeunit = SingleCodeUnit(None, filename) |
---|
54 | codeunit.module_definition = 'void %s()' % function |
---|
55 | self.codeunits[filename] = codeunit |
---|
56 | if function not in self.functions: |
---|
57 | self.functions.append(function) |
---|
58 | self._current = codeunit |
---|
59 | |
---|
60 | |
---|
61 | def Current(self): |
---|
62 | return self._current |
---|
63 | |
---|
64 | current = property(Current, SetCurrent) |
---|
65 | |
---|
66 | |
---|
67 | def Write(self, section, code): |
---|
68 | if self._current is not None: |
---|
69 | self.current.Write(section, code) |
---|
70 | |
---|
71 | |
---|
72 | def Section(self, section): |
---|
73 | if self._current is not None: |
---|
74 | return self.current.Section(section) |
---|
75 | |
---|
76 | |
---|
77 | def _CreateOutputDir(self): |
---|
78 | try: |
---|
79 | os.mkdir(self.outdir) |
---|
80 | except OSError: pass # already created |
---|
81 | |
---|
82 | |
---|
83 | def Save(self): |
---|
84 | # create the directory where all the files will go |
---|
85 | self._CreateOutputDir(); |
---|
86 | # order all code units by filename, and merge them all |
---|
87 | codeunits = {} # filename => list of codeunits |
---|
88 | |
---|
89 | # While ordering all code units by file name, the first code |
---|
90 | # unit in the list of code units is used as the main unit |
---|
91 | # which dumps all the include, declaration and |
---|
92 | # declaration-outside sections at the top of the file. |
---|
93 | for filename, codeunit in self.codeunits.items(): |
---|
94 | if filename not in codeunits: |
---|
95 | # this codeunit is the main codeunit. |
---|
96 | codeunits[filename] = [codeunit] |
---|
97 | codeunit.Merge(self.all) |
---|
98 | else: |
---|
99 | main_unit = codeunits[filename][0] |
---|
100 | for section in ('include', 'declaration', 'declaration-outside'): |
---|
101 | main_unit.code[section] = main_unit.code[section] + codeunit.code[section] |
---|
102 | codeunit.code[section] = '' |
---|
103 | codeunits[filename].append(codeunit) |
---|
104 | |
---|
105 | # Now write all the codeunits appending them correctly. |
---|
106 | for file_units in codeunits.values(): |
---|
107 | append = False |
---|
108 | for codeunit in file_units: |
---|
109 | codeunit.Save(append) |
---|
110 | if not append: |
---|
111 | append = True |
---|
112 | |
---|
113 | |
---|
114 | def GenerateMain(self, interfaces): |
---|
115 | # generate the main cpp |
---|
116 | filename = os.path.join(self.outdir, '_main.cpp') |
---|
117 | fout = SmartFile(filename, 'w') |
---|
118 | fout.write(utils.left_equals('Include')) |
---|
119 | fout.write('#include <boost/python/module.hpp>\n\n') |
---|
120 | fout.write(utils.left_equals('Exports')) |
---|
121 | functions = [self._FunctionName(x) for x in interfaces] |
---|
122 | for function in functions: |
---|
123 | fout.write('void %s();\n' % function) |
---|
124 | fout.write('\n') |
---|
125 | fout.write(utils.left_equals('Module')) |
---|
126 | fout.write('BOOST_PYTHON_MODULE(%s)\n' % self.modulename) |
---|
127 | fout.write('{\n') |
---|
128 | indent = ' ' * 4 |
---|
129 | for function in functions: |
---|
130 | fout.write(indent) |
---|
131 | fout.write('%s();\n' % function) |
---|
132 | fout.write('}\n') |
---|
133 | |
---|
134 | |
---|
135 | |
---|