summaryrefslogtreecommitdiff
path: root/libs/python/pyste
diff options
context:
space:
mode:
Diffstat (limited to 'libs/python/pyste')
-rw-r--r--libs/python/pyste/NEWS212
-rw-r--r--libs/python/pyste/README35
-rw-r--r--libs/python/pyste/TODO18
-rw-r--r--libs/python/pyste/dist/create_build.py55
-rw-r--r--libs/python/pyste/dist/setup.py10
-rw-r--r--libs/python/pyste/doc/adding_new_methods.html79
-rw-r--r--libs/python/pyste/doc/exporting_an_entire_header.html85
-rw-r--r--libs/python/pyste/doc/global_variables.html49
-rw-r--r--libs/python/pyste/doc/inserting_code.html72
-rw-r--r--libs/python/pyste/doc/introduction.html73
-rw-r--r--libs/python/pyste/doc/policies.html90
-rw-r--r--libs/python/pyste/doc/pyste.txt664
-rw-r--r--libs/python/pyste/doc/renaming_and_excluding.html87
-rw-r--r--libs/python/pyste/doc/running_pyste.html200
-rw-r--r--libs/python/pyste/doc/smart_pointers.html84
-rw-r--r--libs/python/pyste/doc/templates.html102
-rw-r--r--libs/python/pyste/doc/the_interface_files.html102
-rw-r--r--libs/python/pyste/doc/theme/alert.gifbin0 -> 577 bytes
-rw-r--r--libs/python/pyste/doc/theme/arrow.gifbin0 -> 70 bytes
-rw-r--r--libs/python/pyste/doc/theme/bkd.gifbin0 -> 1317 bytes
-rw-r--r--libs/python/pyste/doc/theme/bkd2.gifbin0 -> 2543 bytes
-rw-r--r--libs/python/pyste/doc/theme/bulb.gifbin0 -> 944 bytes
-rw-r--r--libs/python/pyste/doc/theme/bullet.gifbin0 -> 152 bytes
-rw-r--r--libs/python/pyste/doc/theme/l_arr.gifbin0 -> 147 bytes
-rw-r--r--libs/python/pyste/doc/theme/l_arr_disabled.gifbin0 -> 91 bytes
-rw-r--r--libs/python/pyste/doc/theme/note.gifbin0 -> 151 bytes
-rw-r--r--libs/python/pyste/doc/theme/r_arr.gifbin0 -> 147 bytes
-rw-r--r--libs/python/pyste/doc/theme/r_arr_disabled.gifbin0 -> 91 bytes
-rw-r--r--libs/python/pyste/doc/theme/smiley.gifbin0 -> 879 bytes
-rw-r--r--libs/python/pyste/doc/theme/style.css178
-rw-r--r--libs/python/pyste/doc/theme/u_arr.gifbin0 -> 170 bytes
-rw-r--r--libs/python/pyste/doc/wrappers.html124
-rw-r--r--libs/python/pyste/index.html90
-rw-r--r--libs/python/pyste/install/pyste.py8
-rw-r--r--libs/python/pyste/install/setup.py20
-rw-r--r--libs/python/pyste/src/Pyste/ClassExporter.py918
-rw-r--r--libs/python/pyste/src/Pyste/CodeExporter.py26
-rw-r--r--libs/python/pyste/src/Pyste/CppParser.py247
-rw-r--r--libs/python/pyste/src/Pyste/EnumExporter.py58
-rw-r--r--libs/python/pyste/src/Pyste/Exporter.py94
-rw-r--r--libs/python/pyste/src/Pyste/FunctionExporter.py92
-rw-r--r--libs/python/pyste/src/Pyste/GCCXMLParser.py478
-rw-r--r--libs/python/pyste/src/Pyste/HeaderExporter.py81
-rw-r--r--libs/python/pyste/src/Pyste/MultipleCodeUnit.py135
-rw-r--r--libs/python/pyste/src/Pyste/SingleCodeUnit.py121
-rw-r--r--libs/python/pyste/src/Pyste/SmartFile.py60
-rw-r--r--libs/python/pyste/src/Pyste/VarExporter.py40
-rw-r--r--libs/python/pyste/src/Pyste/__init__.py6
-rw-r--r--libs/python/pyste/src/Pyste/declarations.py653
-rw-r--r--libs/python/pyste/src/Pyste/exporters.py12
-rw-r--r--libs/python/pyste/src/Pyste/exporterutils.py87
-rw-r--r--libs/python/pyste/src/Pyste/infos.py259
-rw-r--r--libs/python/pyste/src/Pyste/policies.py95
-rw-r--r--libs/python/pyste/src/Pyste/pyste.py424
-rw-r--r--libs/python/pyste/src/Pyste/settings.py21
-rw-r--r--libs/python/pyste/src/Pyste/utils.py78
-rw-r--r--libs/python/pyste/tests/GCCXMLParserUT.py341
-rw-r--r--libs/python/pyste/tests/SmartFileUT.py84
-rw-r--r--libs/python/pyste/tests/abstract_test.h22
-rw-r--r--libs/python/pyste/tests/abstract_test.pyste3
-rw-r--r--libs/python/pyste/tests/abstract_testUT.py26
-rw-r--r--libs/python/pyste/tests/add_test.h18
-rw-r--r--libs/python/pyste/tests/add_test.pyste2
-rw-r--r--libs/python/pyste/tests/add_testUT.py16
-rw-r--r--libs/python/pyste/tests/basic.cpp13
-rw-r--r--libs/python/pyste/tests/basic.h69
-rw-r--r--libs/python/pyste/tests/basic.pyste5
-rw-r--r--libs/python/pyste/tests/basicUT.py73
-rw-r--r--libs/python/pyste/tests/code_test.h8
-rw-r--r--libs/python/pyste/tests/code_test.pyste9
-rw-r--r--libs/python/pyste/tests/code_testUT.py18
-rw-r--r--libs/python/pyste/tests/enums.h34
-rw-r--r--libs/python/pyste/tests/enums.pyste8
-rw-r--r--libs/python/pyste/tests/enumsUT.py24
-rw-r--r--libs/python/pyste/tests/header_test.h43
-rw-r--r--libs/python/pyste/tests/header_test.pyste4
-rw-r--r--libs/python/pyste/tests/header_testUT.py27
-rw-r--r--libs/python/pyste/tests/infosUT.py55
-rw-r--r--libs/python/pyste/tests/inherit.cpp8
-rw-r--r--libs/python/pyste/tests/inherit.h43
-rw-r--r--libs/python/pyste/tests/inherit.pyste8
-rw-r--r--libs/python/pyste/tests/inherit2.h35
-rw-r--r--libs/python/pyste/tests/inherit2.pyste2
-rw-r--r--libs/python/pyste/tests/inherit2UT.py31
-rw-r--r--libs/python/pyste/tests/inherit3.h46
-rw-r--r--libs/python/pyste/tests/inherit3.pyste2
-rw-r--r--libs/python/pyste/tests/inherit3UT.py27
-rw-r--r--libs/python/pyste/tests/inherit4.h23
-rw-r--r--libs/python/pyste/tests/inherit4.pyste3
-rw-r--r--libs/python/pyste/tests/inherit4UT.py31
-rw-r--r--libs/python/pyste/tests/inheritUT.py33
-rw-r--r--libs/python/pyste/tests/nested.cpp9
-rw-r--r--libs/python/pyste/tests/nested.h32
-rw-r--r--libs/python/pyste/tests/nested.pyste1
-rw-r--r--libs/python/pyste/tests/nestedUT.py19
-rw-r--r--libs/python/pyste/tests/opaque.h57
-rw-r--r--libs/python/pyste/tests/opaque.pyste7
-rw-r--r--libs/python/pyste/tests/opaqueUT.py24
-rw-r--r--libs/python/pyste/tests/operators.cpp8
-rw-r--r--libs/python/pyste/tests/operators.h52
-rw-r--r--libs/python/pyste/tests/operators.pyste2
-rw-r--r--libs/python/pyste/tests/operatorsUT.py30
-rw-r--r--libs/python/pyste/tests/policiesUT.py67
-rw-r--r--libs/python/pyste/tests/runtests.py21
-rw-r--r--libs/python/pyste/tests/smart_ptr.h50
-rw-r--r--libs/python/pyste/tests/smart_ptr.pyste13
-rw-r--r--libs/python/pyste/tests/smart_ptrUT.py22
-rw-r--r--libs/python/pyste/tests/templates.h15
-rw-r--r--libs/python/pyste/tests/templates.pyste8
-rw-r--r--libs/python/pyste/tests/templatesUT.py30
-rw-r--r--libs/python/pyste/tests/test_all.py140
-rw-r--r--libs/python/pyste/tests/vars.cpp12
-rw-r--r--libs/python/pyste/tests/vars.h24
-rw-r--r--libs/python/pyste/tests/vars.pyste1
-rw-r--r--libs/python/pyste/tests/varsUT.py22
-rw-r--r--libs/python/pyste/tests/virtual.cpp75
-rw-r--r--libs/python/pyste/tests/virtual.h41
-rw-r--r--libs/python/pyste/tests/virtual.pyste6
-rw-r--r--libs/python/pyste/tests/virtual2.h34
-rw-r--r--libs/python/pyste/tests/virtual2.pyste6
-rw-r--r--libs/python/pyste/tests/virtual2UT.py40
-rw-r--r--libs/python/pyste/tests/virtualUT.py55
-rw-r--r--libs/python/pyste/tests/wrappertest.h51
-rw-r--r--libs/python/pyste/tests/wrappertest.pyste21
-rw-r--r--libs/python/pyste/tests/wrappertestUT.py24
-rw-r--r--libs/python/pyste/tests/wrappertest_wrappers.h33
126 files changed, 8668 insertions, 0 deletions
diff --git a/libs/python/pyste/NEWS b/libs/python/pyste/NEWS
new file mode 100644
index 000000000..31a5ceba2
--- /dev/null
+++ b/libs/python/pyste/NEWS
@@ -0,0 +1,212 @@
+.. Copyright Bruno da Silva de Oliveira 2006. Distributed under 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)
+
+25 April 2005
+- Fixed bug where the code for wrappers of member functions were defined outside
+the pyste namespace. Reported by Dan Haffey.
+
+9 October 2004
+- Applied a patch by Christian Hudon that fixed an issue with files
+that had a tail and relative includes.
+
+18 July 2004
+- Applied a patch by Paul Bridger that solves some problems for wrapper
+methods.
+- Applied a patch by Baptiste Lepilleur that allows the user to inject
+code inside the class definition.
+- Applied another patch by Baptiste Lepilleur that inserts two new command-line
+options that helps with writing makefiles.
+
+27 May 2004
+Applied patch by Paul Bridger that solves a problem on windows regarding
+spaces on paths. Thanks Paul!
+
+Applied another patch that fixes the module name if pyste is run from
+another directory of where the .pyste file is located. Patch contributted
+by Paul Bridger.
+
+17 May 2004
+Applied a patch by Roman Yakovenko that makes the export of unnamed enums
+better. Thanks Roman!
+
+23 October 2003
+Fixed bug where a class would appear more than one in the generated code.
+
+6 October 2003
+Fixed bug reported by Niall Douglas (using his patch) about UniqueInt not
+appearing correctly with --multiple.
+
+Added precompiled header support on windows systems (using #pragma hdrstop).
+Suggested by Niall Douglas.
+
+Fixed a bug with -I directive and AllFromHeader. Reported by Scott Snyder.
+
+4 October 2003
+Added return_self, thanks for Niall Douglas for pointing out that it was
+missing.
+
+Added --file-list, where you can pass a file where the pyste files are listed
+one per line. Also suggested by Niall Douglas.
+
+Documentation has been finally updated, after a long wait. Please let me know
+if you spot any mistake!
+
+2 October 2003
+Scott Snyder found a typo in ClassExporter that prevented -= and *= operators
+from being exported. Thanks Scott!
+
+20 September 2003
+Added return_by_value in the list of policies supported. Thanks to Niall
+Douglas for the remainder.
+
+19 September 2003
+Better support for unnamed enums, plus they are by default exported to the
+parent's namespace. Normal enums can have the same behaviour using the function
+export_values on the Enum object. Feature requested by Niall Douglas.
+
+10 September 2003
+A new variable is accessible in the Pyste files: INTERFACE_FILE contains the
+full path of the pyste file.
+
+4 September 2003
+Now it is possible to override protected and private pure virtual functions
+in Python, as requested by Roman Yakovenko.
+
+23 August 2003
+Fixed bug where some Imports where not writing their include files.
+Now whenever the declarations change, the cache files are rebuilt
+automatically.
+
+19 August 2003
+Fixed a bug related to the generation of the bases<> template.
+
+17 August 2003
+Added support for insertion of user code in the generated code.
+
+16 August 2003
+Applied a patch by Gottfried Ganssauge that adds exception specifiers to
+wrapper functions and pointer declarations. Thanks a lot Gottfried!!
+
+Applied a patch by Prabhu Ramachandran that fixes ae problem with the
+pure virtual method generation. Thanks again Prabhu!
+
+10 August 2003
+Support for incremental generation of the code has been added. This changes
+how --multiple works; documentation of this new feature will follow. Thanks
+to Prabhu Ramachandran, that saw the need for this feature and discussed a
+solution.
+
+Automatically convert \ to / in Windows systems before passing the paths to
+gccxml.
+
+Fixed a bug reported by Prabhu Ramachandran, where in some classes the virtual
+methods were being definied incorrectly. Thanks a lot Prabhu!
+
+7 July 2003
+Applied 2 patches by Prabhu Ramachandran: a fix in the new --multiple method,
+and two new functions "hold_with_shared_ptr" and its counterpart for auto_ptr.
+Thanks a lot Prabhu!
+
+Fixed a bug where the macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID was being
+called multiple times for the same type.
+Thanks to Gottfried Ganßauge for reporting this!
+
+Fixed bug where using AllFromHeader didn't use bases<> when exporting
+hierarchies.
+
+Fixed the staticmethod bug.
+
+5 July 2003
+Changed how --multiple works: now it generates one cpp file for each pyste
+file, makeing easier to integrate Pyste with build systems.
+
+4 July 2003
+Applied patch that solved a bug in ClassExporter and added a distutils install
+script (install/setup.py), both contributed by Prabhu Ramachandran.
+Thanks Prabhu!
+
+2 July 2003
+Jim Wilson found a bug where types like "char**" were being interpreted as
+"char*". Thanks Jim!
+
+16 June 2003
+Thanks to discussions with David Abrahams and Roman Sulzhyk, some behaviours
+have changed:
+
+- If you export a derived class without exporting its base classes, the derived
+ class will explicitly export the bases's methods and attributes. Before, if
+ you were interested in the bases's methods, you had to export the base
+ classes too.
+
+- Added a new function, no_override. When a member function is specified as
+ "no_override", no virtual wrappers are generated for it, improving
+ performance and letting the code more clean.
+
+- There was a bug in which the policy of virtual member functions was being
+ ignored (patch by Roman Sulzhyk).
+
+Thanks again to Roman Sulzhyk for the patches and discussion in the c++-sig.
+
+4 June 2003
+Major improvements in memory usage.
+
+3 June 2003
+Appliced a patch from Giulio Eulisse that allows unnamed enumerations to be
+exported with an AllFromHeader construct. Thanks a lot Giulio!
+
+2 June 2003
+Added a new construct, add_method. See documentation.
+
+23 May 2003
+Support for global variables added.
+Various bug fixes.
+
+08 May 2003
+Fixed bug where in a certain cases the GCCXMLParser would end up with multiple
+declarations of the same class
+
+22 Apr 2003
+- Now shows a warning when the user tries to export a forward-declared class.
+ Forward-declared classes are ignored by the AllFromHeader construct.
+- Fixed a bug where classes, functions and enums where being exported, even if
+ excluded from a AllFromHeader construct.
+
+16 Apr 2003
+Added a more generic (but ugly) code to declare the smart pointer converters.
+
+07 Apr 2003
+- Removed the warnings about forward declarations: it was not accurate enough.
+ Another strategy must be thought of.
+- Fixed bug in the --multiple mode, where the order of the class instantiations
+ could end up wrong.
+- Lots of fixes in the documentation, pointed out by Dirk Gerrits. Thanks Dirk!
+- Fixed support for the return_opaque_pointer policy (the support macro was not
+ being declared).
+
+
+06 Apr 2003
+Support for the improved static data members support of Boost.Python.
+
+05 Apr 2003
+New option for generating the bindings: --multiple.
+
+02 Apr 2003
+Forward declarations are now detected and a warning is generated.
+
+24 Mar 2003
+Default policy for functions/methods that return const T& is now
+return_value_policy<copy_const_reference>().
+
+22 Mar 2003
+Exporting virtual methods of the base classes in the derived classes too.
+
+21 Mar 2003
+Added manual support for boost::shared_ptr and std::auto_ptr (see doc).
+
+19 Mar 2003
+Added support for int, double, float and long operators acting as expected in
+python.
+
+14 Mar 2003
+Fixed bug: Wrappers for protected and virtual methods were not being generated.
diff --git a/libs/python/pyste/README b/libs/python/pyste/README
new file mode 100644
index 000000000..c378f3916
--- /dev/null
+++ b/libs/python/pyste/README
@@ -0,0 +1,35 @@
+.. Copyright Bruno da Silva de Oliveira 2006. Distributed under 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)
+
+Pyste - Python Semi-Automatic Exporter
+======================================
+
+Pyste is a Boost.Python code generator. The user specifies the classes and
+functions to be exported using a simple interface file, which following the
+Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
+parse all the headers and extract the necessary information to automatically
+generate C++ code.
+
+The documentation can be found in the file index.html accompaning this README.
+
+Enjoy!
+Bruno da Silva de Oliveira (nicodemus@esss.com.br)
+
+Thanks
+======
+
+- David Abrahams, creator of Boost.Python, for tips on the syntax of the interface
+ file and support.
+- Marcelo Camelo, for design tips, support and inspiration for this project.
+ Also, the name was his idea. 8)
+- Brad King, creator of the excellent GCCXML (http://www.gccxml.org)
+- Fredrik Lundh, creator of the elementtree library (http://effbot.org)
+
+Bugs
+====
+
+Pyste is a young tool, so please help it to get better! Send bug reports to
+nicodemus@esss.com.br, accompaining the stack trace in case of exceptions.
+If possible, run pyste with --debug, and send the resulting xmls too (pyste
+will output a xml file with the same of each header it parsed).
diff --git a/libs/python/pyste/TODO b/libs/python/pyste/TODO
new file mode 100644
index 000000000..0b3c9024f
--- /dev/null
+++ b/libs/python/pyste/TODO
@@ -0,0 +1,18 @@
+.. Copyright Bruno da Silva de Oliveira 2006. Distributed under 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)
+
+- Make Pyste accept already-generated xml files
+
+- throw() declaration in virtual wrapper's member functions
+
+- Allow protected methods to be overriden in Python
+
+- Expose programmability to the Pyste files (listing members of a class, for
+ instance)
+
+- Virtual operators
+
+- args() support
+
+- set policies to methods with the same name
diff --git a/libs/python/pyste/dist/create_build.py b/libs/python/pyste/dist/create_build.py
new file mode 100644
index 000000000..a68369951
--- /dev/null
+++ b/libs/python/pyste/dist/create_build.py
@@ -0,0 +1,55 @@
+# Copyright Bruno da Silva de Oliveira 2006. Distributed under 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)
+
+import os
+import sys
+import shutil
+import fnmatch
+from zipfile import ZipFile, ZIP_DEFLATED
+
+def findfiles(directory, mask):
+ def visit(files, dir, names):
+ for name in names:
+ if fnmatch.fnmatch(name, mask):
+ files.append(os.path.join(dir, name))
+ files = []
+ os.path.walk(directory, visit, files)
+ return files
+
+
+def main():
+ # test if PyXML is installed
+ try:
+ import _xmlplus.parsers.expat
+ pyxml = '--includes _xmlplus.parsers.expat'
+ except ImportError:
+ pyxml = ''
+ # create exe
+ status = os.system('python setup.py py2exe %s >& build.log' % pyxml)
+ if status != 0:
+ raise RuntimeError, 'Error creating EXE'
+
+ # create distribution
+ import pyste
+ version = pyste.__VERSION__
+ zip = ZipFile('pyste-%s.zip' % version, 'w', ZIP_DEFLATED)
+ # include the base files
+ dist_dir = 'dist/pyste'
+ for basefile in os.listdir(dist_dir):
+ zip.write(os.path.join(dist_dir, basefile), os.path.join('pyste', basefile))
+ # include documentation
+ for doc_file in findfiles('../doc', '*.*'):
+ dest_name = os.path.join('pyste/doc', doc_file[3:])
+ zip.write(doc_file, dest_name)
+ zip.write('../index.html', 'pyste/doc/index.html')
+ zip.close()
+ # cleanup
+ os.remove('build.log')
+ shutil.rmtree('build')
+ shutil.rmtree('dist')
+
+
+if __name__ == '__main__':
+ sys.path.append('../src')
+ main()
diff --git a/libs/python/pyste/dist/setup.py b/libs/python/pyste/dist/setup.py
new file mode 100644
index 000000000..fc7c74e21
--- /dev/null
+++ b/libs/python/pyste/dist/setup.py
@@ -0,0 +1,10 @@
+# Copyright Bruno da Silva de Oliveira 2006. Distributed under 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 distutils.core import setup
+import py2exe
+import sys
+
+sys.path.append('../src')
+setup(name='pyste', scripts=['../src/pyste.py'])
diff --git a/libs/python/pyste/doc/adding_new_methods.html b/libs/python/pyste/doc/adding_new_methods.html
new file mode 100644
index 000000000..afa772bcc
--- /dev/null
+++ b/libs/python/pyste/doc/adding_new_methods.html
@@ -0,0 +1,79 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Adding New Methods</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="global_variables.html">
+<link rel="next" href="inserting_code.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Adding New Methods</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="global_variables.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="inserting_code.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+Suppose that you want to add a function to a class, turning it into a member
+function:</p>
+<code><pre>
+ <span class=keyword>struct </span><span class=identifier>World
+ </span><span class=special>{
+ </span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
+ };
+
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>(</span><span class=identifier>World</span><span class=special>&amp; </span><span class=identifier>w</span><span class=special>)
+ {
+ </span><span class=keyword>return </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>msg</span><span class=special>;
+ }
+</span></pre></code>
+<p>
+Here, we want to make <tt>greet</tt> work as a member function of the class <tt>World</tt>. We do
+that using the <tt>add_method</tt> construct:</p>
+<code><pre>
+ <span class=identifier>W </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>add_method</span><span class=special>(</span><span class=identifier>W</span><span class=special>, </span><span class=string>&quot;greet&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Notice also that then you can rename it, set its policy, just like a regular
+member function:</p>
+<code><pre>
+ <span class=identifier>rename</span><span class=special>(</span><span class=identifier>W</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=literal>'Greet'</span><span class=special>)
+</span></pre></code>
+<p>
+Now from Python:</p>
+<code><pre>
+ <span class=special>&gt;&gt;&gt; </span><span class=identifier>import </span><span class=identifier>hello
+ </span><span class=special>&gt;&gt;&gt; </span><span class=identifier>w </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
+ &gt;&gt;&gt; </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>set</span><span class=special>(</span><span class=literal>'Ni'</span><span class=special>)
+ &gt;&gt;&gt; </span><span class=identifier>w</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
+ </span><span class=literal>'Ni'
+ </span><span class=special>&gt;&gt;&gt; </span><span class=identifier>print </span><span class=literal>'Oh no! The knights who say Ni!'
+ </span><span class=identifier>Oh </span><span class=identifier>no</span><span class=special>! </span><span class=identifier>The </span><span class=identifier>knights </span><span class=identifier>who </span><span class=identifier>say </span><span class=identifier>Ni</span><span class=special>!
+</span></pre></code>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="global_variables.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="inserting_code.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/exporting_an_entire_header.html b/libs/python/pyste/doc/exporting_an_entire_header.html
new file mode 100644
index 000000000..db25325ca
--- /dev/null
+++ b/libs/python/pyste/doc/exporting_an_entire_header.html
@@ -0,0 +1,85 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Exporting An Entire Header</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="wrappers.html">
+<link rel="next" href="smart_pointers.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Exporting An Entire Header</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="wrappers.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="smart_pointers.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+Pyste also supports a mechanism to export all declarations found in a header
+file. Suppose again our file, <tt>hello.h</tt>:</p>
+<code><pre>
+ <span class=keyword>struct </span><span class=identifier>World
+ </span><span class=special>{
+ </span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) {}
+ </span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
+ };
+
+ </span><span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
+
+ </span><span class=keyword>void </span><span class=identifier>show</span><span class=special>(</span><span class=identifier>choice </span><span class=identifier>c</span><span class=special>) { </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>&quot;value: &quot; </span><span class=special>&lt;&lt; (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>; }
+</span></pre></code>
+<p>
+You can just use the <tt>AllFromHeader</tt> construct:</p>
+<code><pre>
+ <span class=identifier>hello </span><span class=special>= </span><span class=identifier>AllFromHeader</span><span class=special>(</span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+this will export all the declarations found in <tt>hello.h</tt>, which is equivalent
+to write:</p>
+<code><pre>
+ <span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;show&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Note that you can still use the functions <tt>rename</tt>, <tt>set_policy</tt>, <tt>exclude</tt>, etc. Just access
+the members of the header object like this:</p>
+<code><pre>
+ <span class=identifier>rename</span><span class=special>(</span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=string>&quot;Greet&quot;</span><span class=special>)
+ </span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>set</span><span class=special>, </span><span class=string>&quot;Set&quot;</span><span class=special>)
+</span></pre></code>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+
+<img src="theme/note.gif"></img> <b>AllFromHeader is broken</b> in some cases. Until it is fixed,
+use at you own risk.
+ </td>
+ </tr>
+</table>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="wrappers.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="smart_pointers.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/global_variables.html b/libs/python/pyste/doc/global_variables.html
new file mode 100644
index 000000000..0efd2950b
--- /dev/null
+++ b/libs/python/pyste/doc/global_variables.html
@@ -0,0 +1,49 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Global Variables</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="smart_pointers.html">
+<link rel="next" href="adding_new_methods.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Global Variables</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="smart_pointers.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="adding_new_methods.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+To export global variables, use the <tt>Var</tt> construct:</p>
+<code><pre>
+ <span class=identifier>Var</span><span class=special>(</span><span class=string>&quot;myglobal&quot;</span><span class=special>, </span><span class=string>&quot;foo.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Beware of non-const global variables: changes in Python won't reflect in C++!
+If you really must change them in Python, you will have to write some accessor
+functions, and export those.</p>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="smart_pointers.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="adding_new_methods.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/inserting_code.html b/libs/python/pyste/doc/inserting_code.html
new file mode 100644
index 000000000..97eb70f38
--- /dev/null
+++ b/libs/python/pyste/doc/inserting_code.html
@@ -0,0 +1,72 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Inserting Code</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="adding_new_methods.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Inserting Code</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="adding_new_methods.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
+ </tr>
+</table>
+<p>
+You can insert arbitrary code in the generated cpps, just use the functions
+<tt>declaration_code</tt> and <tt>module_code</tt>. This will insert the given string in the
+respective sections. Example:</p>
+<code><pre>
+ ##<span class=identifier>file </span><span class=identifier>A</span><span class=special>.</span><span class=identifier>pyste
+ </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;A&quot;</span><span class=special>, </span><span class=string>&quot;A.h&quot;</span><span class=special>)
+ </span><span class=identifier>declaration_code</span><span class=special>(</span><span class=string>&quot;/* declaration_code() comes here */\n&quot;</span><span class=special>)
+ </span><span class=identifier>module_code</span><span class=special>(</span><span class=string>&quot;/* module_code() comes here */\n&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Will generate:</p>
+<code><pre>
+ <span class=comment>// Includes ====================================================================
+ </span><span class=preprocessor>#include </span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;
+
+ // </span><span class=identifier>Using </span><span class=special>=======================================================================
+ </span><span class=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
+
+ // </span><span class=identifier>Declarations </span><span class=special>================================================================
+
+ /* </span><span class=identifier>declaration_code</span><span class=special>() </span><span class=identifier>comes </span><span class=identifier>here </span><span class=special>*/
+
+ // </span><span class=identifier>Module </span><span class=special>======================================================================
+ </span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>A</span><span class=special>)
+ {
+ </span><span class=identifier>class_</span><span class=special>&lt; </span><span class=identifier>A </span><span class=special>&gt;(</span><span class=string>&quot;A&quot;</span><span class=special>, </span><span class=identifier>init</span><span class=special>&lt; &gt;())
+ .</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>init</span><span class=special>&lt; </span><span class=keyword>const </span><span class=identifier>A</span><span class=special>&amp; &gt;())
+ ;
+
+ /* </span><span class=identifier>module_code</span><span class=special>() </span><span class=identifier>comes </span><span class=identifier>here </span><span class=special>*/
+ }
+</span></pre></code>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="adding_new_methods.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/introduction.html b/libs/python/pyste/doc/introduction.html
new file mode 100644
index 000000000..943884931
--- /dev/null
+++ b/libs/python/pyste/doc/introduction.html
@@ -0,0 +1,73 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Introduction</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="next" href="running_pyste.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Introduction</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
+ <td width="20"><a href="running_pyste.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<a name="what_is_pyste_"></a><h2>What is Pyste?</h2><p>
+Pyste is a <a href="../../index.html">
+Boost.Python</a> code generator. The user specifies the classes and
+functions to be exported using a simple <i>interface file</i>, which following the
+<a href="../../index.html">
+Boost.Python</a>'s philosophy, is simple Python code. Pyste then uses <a href="http://www.gccxml.org">
+GCCXML</a> to
+parse all the headers and extract the necessary information to automatically
+generate C++ code.</p>
+<a name="example"></a><h2>Example</h2><p>
+Let's borrow the class <tt>World</tt> from the <a href="../../doc/tutorial/doc/html/python/exposing.html">
+tutorial</a>: </p>
+<code><pre>
+ <span class=keyword>struct </span><span class=identifier>World
+ </span><span class=special>{
+ </span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
+ };
+</span></pre></code>
+<p>
+Here's the interface file for it, named <tt>world.pyste</tt>:</p>
+<code><pre>
+ <span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;world.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+and that's it!</p>
+<p>
+The next step is invoke Pyste in the command-line:</p>
+<code><pre>python pyste.py --module=hello world.pyste</pre></code><p>
+this will create a file &quot;<tt>hello.cpp</tt>&quot; in the directory where the command was
+run. </p>
+<p>
+Pyste supports the following features:</p>
+<ul><li>Functions</li><li>Classes</li><li>Class Templates</li><li>Virtual Methods</li><li>Overloading</li><li>Attributes </li><li>Enums (both &quot;free&quot; enums and class enums)</li><li>Nested Classes</li><li>Support for <tt>boost::shared_ptr</tt> and <tt>std::auto_ptr</tt></li><li>Global Variables</li></ul><table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
+ <td width="20"><a href="running_pyste.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/policies.html b/libs/python/pyste/doc/policies.html
new file mode 100644
index 000000000..3628093bd
--- /dev/null
+++ b/libs/python/pyste/doc/policies.html
@@ -0,0 +1,90 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Policies</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="renaming_and_excluding.html">
+<link rel="next" href="templates.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Policies</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="renaming_and_excluding.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="templates.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+Even thought Pyste can identify various elements in the C++ code, like virtual
+member functions, attributes, and so on, one thing that it can't do is to
+guess the semantics of functions that return pointers or references. In this
+case, the user must manually specify the policy. Policies are explained in the
+<a href="../../doc/tutorial/doc/html/python/functions.html#python.call_policies">
+tutorial</a>.</p>
+<p>
+The policies in Pyste are named exactly as in <a href="../../index.html">
+Boost.Python</a>, only the syntax is
+slightly different. For instance, this policy:</p>
+<code><pre>
+ <span class=identifier>return_internal_reference</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>&lt;</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>&gt; &gt;()
+</span></pre></code>
+<p>
+becomes in Pyste: </p>
+<code><pre>
+ <span class=identifier>return_internal_reference</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>))
+</span></pre></code>
+<p>
+The user can specify policies for functions and virtual member functions with
+the <tt>set_policy</tt> function:</p>
+<code><pre>
+ <span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>f</span><span class=special>, </span><span class=identifier>return_internal_reference</span><span class=special>())
+ </span><span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>, </span><span class=identifier>return_value_policy</span><span class=special>(</span><span class=identifier>manage_new_object</span><span class=special>))
+</span></pre></code>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+
+<img src="theme/note.gif"></img> <b>What if a function or member function needs a policy and
+the user doesn't set one?</b><br><br> If a function needs a policy and one
+was not set, Pyste will issue a error. The user should then go in the
+interface file and set the policy for it, otherwise the generated cpp won't
+compile.
+ </td>
+ </tr>
+</table>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+
+<img src="theme/note.gif"></img>
+Note that for functions that return <tt>const T&amp;</tt>, the policy
+<tt>return_value_policy&lt;copy_const_reference&gt;()</tt> wil be used by default, because
+that's normally what you want. You can change it to something else if you need
+to, though.
+ </td>
+ </tr>
+</table>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="renaming_and_excluding.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="templates.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/pyste.txt b/libs/python/pyste/doc/pyste.txt
new file mode 100644
index 000000000..186a31cba
--- /dev/null
+++ b/libs/python/pyste/doc/pyste.txt
@@ -0,0 +1,664 @@
+[doc Pyste Documentation]
+
+[/ Copyright 2003 Bruno da Silva de Oliveira and Joel de Guzman.
+Distributed under 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) ]
+
+[def GCCXML [@http://www.gccxml.org GCCXML]]
+[def Boost.Python [@../../index.html Boost.Python]]
+
+[page Introduction]
+
+[h2 What is Pyste?]
+
+Pyste is a Boost.Python code generator. The user specifies the classes and
+functions to be exported using a simple ['interface file], which following the
+Boost.Python's philosophy, is simple Python code. Pyste then uses GCCXML to
+parse all the headers and extract the necessary information to automatically
+generate C++ code.
+
+[h2 Example]
+
+Let's borrow the class [^World] from the [@../../doc/tutorial/doc/exposing_classes.html tutorial]:
+
+ struct World
+ {
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+ std::string msg;
+ };
+
+Here's the interface file for it, named [^world.pyste]:
+
+ Class("World", "world.h")
+
+and that's it!
+
+The next step is invoke Pyste in the command-line:
+
+[pre python pyste.py --module=hello world.pyste]
+
+this will create a file "[^hello.cpp]" in the directory where the command was
+run.
+
+Pyste supports the following features:
+
+* Functions
+* Classes
+* Class Templates
+* Virtual Methods
+* Overloading
+* Attributes
+* Enums (both "free" enums and class enums)
+* Nested Classes
+* Support for [^boost::shared_ptr] and [^std::auto_ptr]
+* Global Variables
+
+[page Running Pyste]
+
+To run Pyste, you will need:
+
+* Python 2.2, available at [@http://www.python.org python's website].
+* The great [@http://effbot.org elementtree] library, from Fredrik Lundh.
+* The excellent GCCXML, from Brad King.
+
+Installation for the tools is available in their respective webpages.
+
+[blurb
+[$theme/note.gif] GCCXML must be accessible in the PATH environment variable, so
+that Pyste can call it. How to do this varies from platform to platform.
+]
+
+[h2 Ok, now what?]
+
+Well, now let's fire it up:
+
+[pre
+'''
+>python pyste.py
+
+Pyste version 0.9.26
+
+Usage:
+ pyste [options] interface-files
+
+where options are:
+ --module=<name> The name of the module that will be generated;
+ defaults to the first interface filename, without
+ the extension.
+ -I <path> Add an include path
+ -D <symbol> Define symbol
+ --multiple Create various cpps, instead of only one
+ (useful during development)
+ --out=<name> Specify output filename (default: <module>.cpp)
+ in --multiple mode, this will be a directory
+ --no-using Do not declare "using namespace boost";
+ use explicit declarations instead
+ --pyste-ns=<name> Set the namespace where new types will be declared;
+ default is the empty namespace
+ --debug Writes the xml for each file parsed in the current
+ directory
+ --cache-dir=<dir> Directory for cache files (speeds up future runs)
+ --only-create-cache Recreates all caches (doesn't generate code).
+ --generate-main Generates the _main.cpp file (in multiple mode)
+ --file-list A file with one pyste file per line. Use as a
+ substitute for passing the files in the command
+ line.
+ -h, --help Print this help and exit
+ -v, --version Print version information
+
+'''
+]
+
+Options explained:
+
+The [^-I] and [^-D] are preprocessor flags, which are needed by GCCXML to parse
+the header files correctly and by Pyste to find the header files declared in the
+interface files.
+
+[^--out] names the output file (default: [^<module>.cpp]), or in multiple mode,
+names a output directory for the files (default: [^<module>]).
+
+[^--no-using] tells Pyste to don't declare "[^using namespace boost;]" in the
+generated cpp, using the namespace boost::python explicitly in all declarations.
+Use only if you're having a name conflict in one of the files.
+
+Use [^--pyste-ns] to change the namespace where new types are declared (for
+instance, the virtual wrappers). Use only if you are having any problems. By
+default, Pyste uses the empty namespace.
+
+[^--debug] will write in the current directory a xml file as outputted by GCCXML
+for each header parsed. Useful for bug reports.
+
+[^--file-list] names a file where each line points to a Pyste file. Use this instead
+to pass the pyste files if you have a lot of them and your shell has some command line
+size limit.
+
+The other options are explained below, in [@#multiple_mode [*Multiple Mode]] and
+[@#cache [*Cache]].
+
+[^-h, --help, -v, --version] are self-explaining, I believe. ;)
+
+So, the usage is simple enough:
+
+[pre >python pyste.py --module=mymodule file.pyste file2.pyste ...]
+
+will generate a file [^mymodule.cpp] in the same dir where the command was
+executed. Now you can compile the file using the same instructions of the
+[@../../doc/tutorial/doc/building_hello_world.html tutorial].
+
+[h2 Wait... how do I set those I and D flags?]
+
+Don't worry: normally GCCXML is already configured correctly for your plataform,
+so the search path to the standard libraries and the standard defines should
+already be set. You only have to set the paths to other libraries that your code
+needs, like Boost, for example.
+
+Plus, Pyste automatically uses the contents of the environment variable
+[^INCLUDE] if it exists. Visual C++ users should run the [^Vcvars32.bat] file,
+which for Visual C++ 6 is normally located at:
+
+ C:\Program Files\Microsoft Visual Studio\VC98\bin\Vcvars32.bat
+
+with that, you should have little trouble setting up the flags.
+
+[blurb [$theme/note.gif][*A note about Psyco][br][br]
+Although you don't have to install [@http://psyco.sourceforge.net/ Psyco] to
+use Pyste, if you do, Pyste will make use of it to speed up the wrapper
+generation. Speed ups of 30% can be achieved, so it's highly recommended.
+]
+
+
+[h2 Multiple Mode]
+
+The multiple mode is useful in large projects, where the presence of multiple
+classes in a single file makes the compilation unpractical (excessive memory
+usage, mostly).
+
+The solution is make Pyste generate multiple files, more specifically one cpp
+file for each Pyste file. This files will contain a function named after the
+file, for instance Export_MyPysteFile, which will contain all the code to export
+the classes, enums, etc. You can pass as much files as you want this way:
+
+[pre >python pyste.py --module=mymodule file1.pyste file2.pyste]
+
+This will create the files [^mymodule/file1.cpp] and [^mymodule/file2.cpp]. You
+can then later do:
+
+[pre >python pyste.py --module=mymodule file3.pyste]
+
+and [^mymodule/file3.cpp] will be generated.
+
+But compiling and linking this files won't be sufficient to generate your
+extension. You have to also generate a file named [^main.cpp]; call pyste with
+[*all] the Pyste files of your extension, and use the [^--generate-main] option:
+
+[pre >python pyste.py --module=mymodule --generate-main file1.pyste file2.pyste file3.pyste]
+
+Now compile and link all this files together and your extension is ready for
+use.
+
+[h2 Cache]
+
+Pyste now supports a form of cache, which is a way to speed up the code
+generation. Most of the time that Pyste takes to generate the code comes from
+having to execute GCCXML (since being a front-end to GCC, it has to compile the
+header files) and reading back the XML generated.
+
+When you use the [^--cache-dir=<dir>] option, Pyste will dump in the specified
+directory the generated XMLs to a file named after the Pyste file, with the
+extension [^.pystec]. The next time you run with this option, Pyste will use
+the cache, instead of calling GCCXML again:
+
+[pre >python pyste.py --module=mymodule --cache-dir=cache file1.pyste]
+
+Will generate [^file1.cpp] and [^cache/file1.pystec]. Next time you execute
+this command, the cache file will be used. Note that Pyste doesn't do any check
+to ensure that the cache is up to date, but you can configure your build system to do that for you.
+
+When you run Pyste with [^--only-create-cache], all the cache files will be
+created again, but no code will be generated.
+
+[page The Interface Files]
+
+The interface files are the heart of Pyste. The user creates one or more
+interface files declaring the classes and functions he wants to export, and then
+invokes Pyste passing the interface files to it. Pyste then generates a single
+cpp file with Boost.Python code, with all the classes and functions exported.
+
+Besides declaring the classes and functions, the user has a number of other
+options, like renaming e excluding classes and member functionis. Those are
+explained later on.
+
+[h2 Basics]
+
+Suppose we have a class and some functions that we want to expose to Python
+declared in the header [^hello.h]:
+
+ struct World
+ {
+ World(std::string msg): msg(msg) {}
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+ std::string msg;
+ };
+
+ enum choice { red, blue };
+
+ namespace test {
+
+ void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
+
+ }
+
+We create a file named [^hello.pyste] and create instances of the classes
+[^Function], [^Class] and [^Enum]:
+
+ Function("test::show", "hello.h")
+ Class("World", "hello.h")
+ Enum("choice", "hello.h")
+
+That will expose the class, the free function and the enum found in [^hello.h].
+
+[h2 Inheritance]
+
+Pyste automatically generates the correct code (specifying [^bases<>] in the
+[^class_] declaration) [*if] the Class() function that exports the base classes
+and their children are in the same Pyste file. If that's not the case, you have
+to indicate that there's a relationship between the Pyste files using the
+[^Import] function specifying the other Pyste file.
+
+Suppose we have two classes, [^A] and [^B], and A is a base class for B. We
+create two Pyste files:
+
+[^A.pyste]:
+
+ Class("A", "A.h")
+
+[^B.pyste]:
+
+ Import("A.pyste")
+ Class("B", "B.h")
+
+Note that we specify that [^B] needs to know about [^A] to be properly exported.
+
+[page:1 Renaming and Excluding]
+
+You can easily rename functions, classes, member functions, attributes, etc. Just use the
+function [^rename], like this:
+
+ World = Class("World", "hello.h")
+ rename(World, "IWorld")
+ show = Function("choice", "hello.h")
+ rename(show, "Show")
+
+You can rename member functions and attributes using this syntax:
+
+ rename(World.greet, "Greet")
+ rename(World.set, "Set")
+ choice = Enum("choice", "hello.h")
+ rename(choice.red, "Red")
+ rename(choice.blue, "Blue")
+
+You can exclude functions, classes, member functions, attributes, etc, in the same way,
+with the function [^exclude]:
+
+ exclude(World.greet)
+ exclude(World.msg)
+
+To access the operators of a class, access the member [^operator] like this
+(supposing that [^C] is a class being exported):
+
+ exclude(C.operator['+'])
+ exclude(C.operator['*'])
+ exclude(C.operator['<<'])
+
+The string inside the brackets is the same as the name of the operator in C++.[br]
+
+[h2 Virtual Member Functions]
+
+Pyste automatically generates wrappers for virtual member functions, but you may
+want to disable this behaviour (for performance reasons, for instance) if you do
+not plan to override the functions in Python. To do this, use the function
+[^final]:
+
+ C = Class('C', 'C.h')
+ final(C.foo) # C::foo is a virtual member function
+
+No virtual wrapper code will be generated for the virtual member function
+C::foo that way.
+
+[page:1 Policies]
+
+Even thought Pyste can identify various elements in the C++ code, like virtual
+member functions, attributes, and so on, one thing that it can't do is to
+guess the semantics of functions that return pointers or references. In this
+case, the user must manually specify the policy. Policies are explained in the
+[@../../doc/tutorial/doc/call_policies.html tutorial].
+
+The policies in Pyste are named exactly as in Boost.Python, only the syntax is
+slightly different. For instance, this policy:
+
+ return_internal_reference<1, with_custodian_and_ward<1, 2> >()
+
+becomes in Pyste:
+
+ return_internal_reference(1, with_custodian_and_ward(1, 2))
+
+The user can specify policies for functions and virtual member functions with
+the [^set_policy] function:
+
+ set_policy(f, return_internal_reference())
+ set_policy(C.foo, return_value_policy(manage_new_object))
+
+[blurb
+[$theme/note.gif] [*What if a function or member function needs a policy and
+the user doesn't set one?][br][br] If a function needs a policy and one
+was not set, Pyste will issue a error. The user should then go in the
+interface file and set the policy for it, otherwise the generated cpp won't
+compile.
+]
+
+[blurb
+[$theme/note.gif]
+Note that for functions that return [^const T&], the policy
+[^return_value_policy<copy_const_reference>()] wil be used by default, because
+that's normally what you want. You can change it to something else if you need
+to, though.
+]
+
+[page:1 Templates]
+
+Template classes can easily be exported too, but you can't export the template
+itself... you have to export instantiations of it! So, if you want to export a
+[^std::vector], you will have to export vectors of int, doubles, etc.
+
+Suppose we have this code:
+
+ template <class T>
+ struct Point
+ {
+ T x;
+ T y;
+ };
+
+And we want to export [^Point]s of int and double:
+
+ Point = Template("Point", "point.h")
+ Point("int")
+ Point("double")
+
+Pyste will assign default names for each instantiation. In this example, those
+would be "[^Point_int]" and "[^Point_double]", but most of the time users will want to
+rename the instantiations:
+
+ Point("int", "IPoint") // renames the instantiation
+ double_inst = Point("double") // another way to do the same
+ rename(double_inst, "DPoint")
+
+Note that you can rename, exclude, set policies, etc, in the [^Template] object
+like you would do with a [^Function] or a [^Class]. This changes affect all
+[*future] instantiations:
+
+ Point = Template("Point", "point.h")
+ Point("float", "FPoint") // will have x and y as data members
+ rename(Point.x, "X")
+ rename(Point.y, "Y")
+ Point("int", "IPoint") // will have X and Y as data members
+ Point("double", "DPoint") // also will have X and Y as data member
+
+If you want to change a option of a particular instantiation, you can do so:
+
+ Point = Template("Point", "point.h")
+ Point("int", "IPoint")
+ d_inst = Point("double", "DPoint")
+ rename(d_inst.x, "X") // only DPoint is affect by this renames,
+ rename(d_inst.y, "Y") // IPoint stays intact
+
+[blurb [$theme/note.gif] [*What if my template accepts more than one type?]
+[br][br]
+When you want to instantiate a template with more than one type, you can pass
+either a string with the types separated by whitespace, or a list of strings
+'''("int double" or ["int", "double"]''' would both work).
+]
+
+[page:1 Wrappers]
+
+Suppose you have this function:
+
+ std::vector<std::string> names();
+
+But you don't want to [@../../doc/v2/faq.html#question2 to export std::vector<std::string>],
+you want this function to return a python list of strings. Boost.Python has
+excellent support for things like that:
+
+ list names_wrapper()
+ {
+ list result;
+ // call original function
+ vector<string> v = names();
+ // put all the strings inside the python list
+ vector<string>::iterator it;
+ for (it = v.begin(); it != v.end(); ++it){
+ result.append(*it);
+ }
+ return result;
+ }
+
+ BOOST_PYTHON_MODULE(test)
+ {
+ def("names", &names_wrapper);
+ }
+
+Nice heh? Pyste supports this mechanism too. You declare the [^names_wrapper]
+function in a header named "[^test_wrappers.h]" and in the interface file:
+
+ Include("test_wrappers.h")
+ names = Function("names", "test.h")
+ set_wrapper(names, "names_wrapper")
+
+You can optionally declare the function in the interface file itself:
+
+ names_wrapper = Wrapper("names_wrapper",
+ """
+ list names_wrapper()
+ {
+ // code to call name() and convert the vector to a list...
+ }
+ """)
+ names = Function("names", "test.h")
+ set_wrapper(names, names_wrapper)
+
+The same mechanism can be used with member functions too. Just remember that
+the first parameter of wrappers for member functions is a pointer to the
+class, as in:
+
+ struct C
+ {
+ std::vector<std::string> names();
+ }
+
+ list names_wrapper(C* c)
+ {
+ // same as before, calling c->names() and converting result to a list
+ }
+
+And then in the interface file:
+
+ C = Class("C", "test.h")
+ set_wrapper(C.names, "names_wrapper")
+
+[blurb
+[$theme/note.gif]Even though Boost.Python accepts either a pointer or a
+reference to the class in wrappers for member functions as the first parameter,
+Pyste expects them to be a [*pointer]. Doing otherwise will prevent your
+code to compile when you set a wrapper for a virtual member function.
+]
+
+[page:1 Exporting An Entire Header]
+
+Pyste also supports a mechanism to export all declarations found in a header
+file. Suppose again our file, [^hello.h]:
+
+ struct World
+ {
+ World(std::string msg): msg(msg) {}
+ void set(std::string msg) { this->msg = msg; }
+ std::string greet() { return msg; }
+ std::string msg;
+ };
+
+ enum choice { red, blue };
+
+ void show(choice c) { std::cout << "value: " << (int)c << std::endl; }
+
+You can just use the [^AllFromHeader] construct:
+
+ hello = AllFromHeader("hello.h")
+
+this will export all the declarations found in [^hello.h], which is equivalent
+to write:
+
+ Class("World", "hello.h")
+ Enum("choice", "hello.h")
+ Function("show", "hello.h")
+
+Note that you can still use the functions [^rename], [^set_policy], [^exclude], etc. Just access
+the members of the header object like this:
+
+ rename(hello.World.greet, "Greet")
+ exclude(hello.World.set, "Set")
+
+[blurb
+[$theme/note.gif] [*AllFromHeader is broken] in some cases. Until it is fixed,
+use at you own risk.
+]
+
+
+[page:1 Smart Pointers]
+
+Pyste for now has manual support for smart pointers. Suppose:
+
+ struct C
+ {
+ int value;
+ };
+
+ boost::shared_ptr<C> newC(int value)
+ {
+ boost::shared_ptr<C> c( new C() );
+ c->value = value;
+ return c;
+ }
+
+ void printC(boost::shared_ptr<C> c)
+ {
+ std::cout << c->value << std::endl;
+ }
+
+To make [^newC] and [^printC] work correctly, you have to tell Pyste that a
+convertor for [^boost::shared_ptr<C>] is needed.
+
+ C = Class('C', 'C.h')
+ use_shared_ptr(C)
+ Function('newC', 'C.h')
+ Function('printC', 'C.h')
+
+For [^std::auto_ptr]'s, use the function [^use_auto_ptr].
+
+This system is temporary, and in the future the converters will automatically be
+exported if needed, without the need to tell Pyste about them explicitly.
+
+[h2 Holders]
+
+If only the converter for the smart pointers is not enough and you need to
+specify the smart pointer as the holder for a class, use the functions
+[^hold_with_shared_ptr] and [^hold_with_auto_ptr]:
+
+ C = Class('C', 'C.h')
+ hold_with_shared_ptr(C)
+ Function('newC', 'C.h')
+ Function('printC', 'C.h')
+
+[page:1 Global Variables]
+
+To export global variables, use the [^Var] construct:
+
+ Var("myglobal", "foo.h")
+
+Beware of non-const global variables: changes in Python won't reflect in C++!
+If you really must change them in Python, you will have to write some accessor
+functions, and export those.
+
+
+[page:1 Adding New Methods]
+
+Suppose that you want to add a function to a class, turning it into a member
+function:
+
+ struct World
+ {
+ void set(std::string msg) { this->msg = msg; }
+ std::string msg;
+ };
+
+ std::string greet(World& w)
+ {
+ return w.msg;
+ }
+
+Here, we want to make [^greet] work as a member function of the class [^World]. We do
+that using the [^add_method] construct:
+
+ W = Class("World", "hello.h")
+ add_method(W, "greet")
+
+Notice also that then you can rename it, set its policy, just like a regular
+member function:
+
+ rename(W.greet, 'Greet')
+
+Now from Python:
+
+ >>> import hello
+ >>> w = hello.World()
+ >>> w.set('Ni')
+ >>> w.greet()
+ 'Ni'
+ >>> print 'Oh no! The knights who say Ni!'
+ Oh no! The knights who say Ni!
+
+
+[page:1 Inserting Code]
+
+You can insert arbitrary code in the generated cpps, just use the functions
+[^declaration_code] and [^module_code]. This will insert the given string in the
+respective sections. Example:
+
+ # file A.pyste
+ Class("A", "A.h")
+ declaration_code("/* declaration_code() comes here */\n")
+ module_code("/* module_code() comes here */\n")
+
+Will generate:
+
+ // Includes ====================================================================
+ #include <boost/python.hpp>
+
+ // Using =======================================================================
+ using namespace boost::python;
+
+ // Declarations ================================================================
+
+ /* declaration_code() comes here */
+
+ // Module ======================================================================
+ BOOST_PYTHON_MODULE(A)
+ {
+ class_< A >("A", init< >())
+ .def(init< const A& >())
+ ;
+
+ /* module_code() comes here */
+ }
diff --git a/libs/python/pyste/doc/renaming_and_excluding.html b/libs/python/pyste/doc/renaming_and_excluding.html
new file mode 100644
index 000000000..ce6654c4a
--- /dev/null
+++ b/libs/python/pyste/doc/renaming_and_excluding.html
@@ -0,0 +1,87 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Renaming and Excluding</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="the_interface_files.html">
+<link rel="next" href="policies.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Renaming and Excluding</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="the_interface_files.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+You can easily rename functions, classes, member functions, attributes, etc. Just use the
+function <tt>rename</tt>, like this:</p>
+<code><pre>
+ <span class=identifier>World </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>, </span><span class=string>&quot;IWorld&quot;</span><span class=special>)
+ </span><span class=identifier>show </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>show</span><span class=special>, </span><span class=string>&quot;Show&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+You can rename member functions and attributes using this syntax:</p>
+<code><pre>
+ <span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=string>&quot;Greet&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>set</span><span class=special>, </span><span class=string>&quot;Set&quot;</span><span class=special>)
+ </span><span class=identifier>choice </span><span class=special>= </span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red</span><span class=special>, </span><span class=string>&quot;Red&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>blue</span><span class=special>, </span><span class=string>&quot;Blue&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+You can exclude functions, classes, member functions, attributes, etc, in the same way,
+with the function <tt>exclude</tt>:</p>
+<code><pre>
+ <span class=identifier>exclude</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>)
+ </span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>msg</span><span class=special>)
+</span></pre></code>
+<p>
+To access the operators of a class, access the member <tt>operator</tt> like this
+(supposing that <tt>C</tt> is a class being exported):</p>
+<code><pre>
+ <span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'+'</span><span class=special>])
+ </span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'*'</span><span class=special>])
+ </span><span class=identifier>exclude</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=keyword>operator</span><span class=special>[</span><span class=literal>'&lt;&lt;'</span><span class=special>])
+</span></pre></code>
+<p>
+The string inside the brackets is the same as the name of the operator in C++.<br></p>
+<a name="virtual_member_functions"></a><h2>Virtual Member Functions</h2><p>
+Pyste automatically generates wrappers for virtual member functions, but you may
+want to disable this behaviour (for performance reasons, for instance) if you do
+not plan to override the functions in Python. To do this, use the function
+<tt>final</tt>:</p>
+<code><pre>
+ <span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+ </span><span class=identifier>final</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>) </span>##<span class=identifier>C</span><span class=special>::</span><span class=identifier>foo </span><span class=identifier>is </span><span class=identifier>a </span><span class=keyword>virtual </span><span class=identifier>member </span><span class=identifier>function
+</span></pre></code>
+<p>
+No virtual wrapper code will be generated for the virtual member function
+C::foo that way.</p>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="the_interface_files.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/running_pyste.html b/libs/python/pyste/doc/running_pyste.html
new file mode 100644
index 000000000..9bd9a3aee
--- /dev/null
+++ b/libs/python/pyste/doc/running_pyste.html
@@ -0,0 +1,200 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Running Pyste</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="introduction.html">
+<link rel="next" href="the_interface_files.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Running Pyste</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="introduction.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="the_interface_files.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+To run Pyste, you will need:</p>
+<ul><li>Python 2.2, available at <a href="http://www.python.org">
+python's website</a>.</li><li>The great <a href="http://effbot.org">
+elementtree</a> library, from Fredrik Lundh.</li><li>The excellent <a href="http://www.gccxml.org">
+GCCXML</a>, from Brad King.</li></ul><p>
+Installation for the tools is available in their respective webpages.</p>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+
+<img src="theme/note.gif"></img> <a href="http://www.gccxml.org">
+GCCXML</a> must be accessible in the PATH environment variable, so
+that Pyste can call it. How to do this varies from platform to platform.
+ </td>
+ </tr>
+</table>
+<a name="ok__now_what_"></a><h2>Ok, now what?</h2><p>
+Well, now let's fire it up:</p>
+<code><pre>
+
+&gt;python pyste.py
+
+Pyste version 0.9.26
+
+Usage:
+ pyste [options] interface-files
+
+where options are:
+ --module=&lt;name&gt; The name of the module that will be generated;
+ defaults to the first interface filename, without
+ the extension.
+ -I &lt;path&gt; Add an include path
+ -D &lt;symbol&gt; Define symbol
+ --multiple Create various cpps, instead of only one
+ (useful during development)
+ --out=&lt;name&gt; Specify output filename (default: &lt;module&gt;.cpp)
+ in --multiple mode, this will be a directory
+ --no-using Do not declare &quot;using namespace boost&quot;;
+ use explicit declarations instead
+ --pyste-ns=&lt;name&gt; Set the namespace where new types will be declared;
+ default is the empty namespace
+ --debug Writes the xml for each file parsed in the current
+ directory
+ --cache-dir=&lt;dir&gt; Directory for cache files (speeds up future runs)
+ --only-create-cache Recreates all caches (doesn't generate code).
+ --generate-main Generates the _main.cpp file (in multiple mode)
+ --file-list A file with one pyste file per line. Use as a
+ substitute for passing the files in the command
+ line.
+ -h, --help Print this help and exit
+ -v, --version Print version information
+
+
+</pre></code><p>
+Options explained:</p>
+<p>
+The <tt>-I</tt> and <tt>-D</tt> are preprocessor flags, which are needed by <a href="http://www.gccxml.org">
+GCCXML</a> to parse
+the header files correctly and by Pyste to find the header files declared in the
+interface files.</p>
+<p>
+<tt>--out</tt> names the output file (default: <tt>&lt;module&gt;.cpp</tt>), or in multiple mode,
+names a output directory for the files (default: <tt>&lt;module&gt;</tt>).</p>
+<p>
+<tt>--no-using</tt> tells Pyste to don't declare &quot;<tt>using namespace boost;</tt>&quot; in the
+generated cpp, using the namespace boost::python explicitly in all declarations.
+Use only if you're having a name conflict in one of the files.</p>
+<p>
+Use <tt>--pyste-ns</tt> to change the namespace where new types are declared (for
+instance, the virtual wrappers). Use only if you are having any problems. By
+default, Pyste uses the empty namespace.</p>
+<p>
+<tt>--debug</tt> will write in the current directory a xml file as outputted by <a href="http://www.gccxml.org">
+GCCXML</a>
+for each header parsed. Useful for bug reports.</p>
+<p>
+<tt>--file-list</tt> names a file where each line points to a Pyste file. Use this instead
+to pass the pyste files if you have a lot of them and your shell has some command line
+size limit.</p>
+<p>
+The other options are explained below, in <a href="#multiple_mode">
+<b>Multiple Mode</b></a> and
+<a href="#cache">
+<b>Cache</b></a>.</p>
+<p>
+<tt>-h, --help, -v, --version</tt> are self-explaining, I believe. ;)</p>
+<p>
+So, the usage is simple enough:</p>
+<code><pre>&gt;python pyste.py --module=mymodule file.pyste file2.pyste ...</pre></code><p>
+will generate a file <tt>mymodule.cpp</tt> in the same dir where the command was
+executed. Now you can compile the file using the same instructions of the
+<a href="../../doc/tutorial/doc/html/python/hello.html">
+tutorial</a>. </p>
+<a name="wait____how_do_i_set_those_i_and_d_flags_"></a><h2>Wait... how do I set those I and D flags?</h2><p>
+Don't worry: normally <a href="http://www.gccxml.org">
+GCCXML</a> is already configured correctly for your plataform,
+so the search path to the standard libraries and the standard defines should
+already be set. You only have to set the paths to other libraries that your code
+needs, like Boost, for example.</p>
+<p>
+Plus, Pyste automatically uses the contents of the environment variable
+<tt>INCLUDE</tt> if it exists. Visual C++ users should run the <tt>Vcvars32.bat</tt> file,
+which for Visual C++ 6 is normally located at:</p>
+<code><pre>
+ <span class=identifier>C</span><span class=special>:\</span><span class=identifier>Program </span><span class=identifier>Files</span><span class=special>\</span><span class=identifier>Microsoft </span><span class=identifier>Visual </span><span class=identifier>Studio</span><span class=special>\</span><span class=identifier>VC98</span><span class=special>\</span><span class=identifier>bin</span><span class=special>\</span><span class=identifier>Vcvars32</span><span class=special>.</span><span class=identifier>bat
+</span></pre></code>
+<p>
+with that, you should have little trouble setting up the flags.</p>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+<img src="theme/note.gif"></img><b>A note about Psyco</b><br><br>
+Although you don't have to install <a href="http://psyco.sourceforge.net/">
+Psyco</a> to
+use Pyste, if you do, Pyste will make use of it to speed up the wrapper
+generation. Speed ups of 30% can be achieved, so it's highly recommended.
+ </td>
+ </tr>
+</table>
+<a name="multiple_mode"></a><h2>Multiple Mode</h2><p>
+The multiple mode is useful in large projects, where the presence of multiple
+classes in a single file makes the compilation unpractical (excessive memory
+usage, mostly). </p>
+<p>
+The solution is make Pyste generate multiple files, more specifically one cpp
+file for each Pyste file. This files will contain a function named after the
+file, for instance Export_MyPysteFile, which will contain all the code to export
+the classes, enums, etc. You can pass as much files as you want this way:</p>
+<code><pre>&gt;python pyste.py --module=mymodule file1.pyste file2.pyste</pre></code><p>
+This will create the files <tt>mymodule/file1.cpp</tt> and <tt>mymodule/file2.cpp</tt>. You
+can then later do:</p>
+<code><pre>&gt;python pyste.py --module=mymodule file3.pyste</pre></code><p>
+and <tt>mymodule/file3.cpp</tt> will be generated.</p>
+<p>
+But compiling and linking this files won't be sufficient to generate your
+extension. You have to also generate a file named <tt>main.cpp</tt>; call pyste with
+<b>all</b> the Pyste files of your extension, and use the <tt>--generate-main</tt> option:</p>
+<code><pre>&gt;python pyste.py --module=mymodule --generate-main file1.pyste file2.pyste file3.pyste</pre></code><p>
+Now compile and link all this files together and your extension is ready for
+use.</p>
+<a name="cache"></a><h2>Cache</h2><p>
+Pyste now supports a form of cache, which is a way to speed up the code
+generation. Most of the time that Pyste takes to generate the code comes from
+having to execute <a href="http://www.gccxml.org">
+GCCXML</a> (since being a front-end to GCC, it has to compile the
+header files) and reading back the XML generated. </p>
+<p>
+When you use the <tt>--cache-dir=&lt;dir&gt;</tt> option, Pyste will dump in the specified
+directory the generated XMLs to a file named after the Pyste file, with the
+extension <tt>.pystec</tt>. The next time you run with this option, Pyste will use
+the cache, instead of calling <a href="http://www.gccxml.org">
+GCCXML</a> again:</p>
+<code><pre>&gt;python pyste.py --module=mymodule --cache-dir=cache file1.pyste</pre></code><p>
+Will generate <tt>file1.cpp</tt> and <tt>cache/file1.pystec</tt>. Next time you execute
+this command, the cache file will be used. Note that Pyste doesn't do any check
+to ensure that the cache is up to date, but you can configure your build system to do that for you.</p>
+<p>
+When you run Pyste with <tt>--only-create-cache</tt>, all the cache files will be
+created again, but no code will be generated.</p>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="introduction.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="the_interface_files.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/smart_pointers.html b/libs/python/pyste/doc/smart_pointers.html
new file mode 100644
index 000000000..cddc96f2f
--- /dev/null
+++ b/libs/python/pyste/doc/smart_pointers.html
@@ -0,0 +1,84 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Smart Pointers</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="exporting_an_entire_header.html">
+<link rel="next" href="global_variables.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Smart Pointers</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="exporting_an_entire_header.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="global_variables.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+Pyste for now has manual support for smart pointers. Suppose:</p>
+<code><pre>
+ <span class=keyword>struct </span><span class=identifier>C
+ </span><span class=special>{
+ </span><span class=keyword>int </span><span class=identifier>value</span><span class=special>;
+ };
+
+ </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>newC</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>value</span><span class=special>)
+ {
+ </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>c</span><span class=special>( </span><span class=keyword>new </span><span class=identifier>C</span><span class=special>() );
+ </span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>value </span><span class=special>= </span><span class=identifier>value</span><span class=special>;
+ </span><span class=keyword>return </span><span class=identifier>c</span><span class=special>;
+ }
+
+ </span><span class=keyword>void </span><span class=identifier>printC</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>shared_ptr</span><span class=special>&lt;</span><span class=identifier>C</span><span class=special>&gt; </span><span class=identifier>c</span><span class=special>)
+ {
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>value </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;
+ }
+</span></pre></code>
+<p>
+To make <tt>newC</tt> and <tt>printC</tt> work correctly, you have to tell Pyste that a
+convertor for <tt>boost::shared_ptr&lt;C&gt;</tt> is needed.</p>
+<code><pre>
+ <span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+ </span><span class=identifier>use_shared_ptr</span><span class=special>(</span><span class=identifier>C</span><span class=special>)
+ </span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'newC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+ </span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'printC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+</span></pre></code>
+<p>
+For <tt>std::auto_ptr</tt>'s, use the function <tt>use_auto_ptr</tt>.</p>
+<p>
+This system is temporary, and in the future the converters will automatically be
+exported if needed, without the need to tell Pyste about them explicitly.</p>
+<a name="holders"></a><h2>Holders</h2><p>
+If only the converter for the smart pointers is not enough and you need to
+specify the smart pointer as the holder for a class, use the functions
+<tt>hold_with_shared_ptr</tt> and <tt>hold_with_auto_ptr</tt>:</p>
+<code><pre>
+ <span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+ </span><span class=identifier>hold_with_shared_ptr</span><span class=special>(</span><span class=identifier>C</span><span class=special>)
+ </span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'newC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+ </span><span class=identifier>Function</span><span class=special>(</span><span class=literal>'printC'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
+</span></pre></code>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="exporting_an_entire_header.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="global_variables.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/templates.html b/libs/python/pyste/doc/templates.html
new file mode 100644
index 000000000..a1c1cfefb
--- /dev/null
+++ b/libs/python/pyste/doc/templates.html
@@ -0,0 +1,102 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Templates</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="policies.html">
+<link rel="next" href="wrappers.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Templates</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="wrappers.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+Template classes can easily be exported too, but you can't export the template
+itself... you have to export instantiations of it! So, if you want to export a
+<tt>std::vector</tt>, you will have to export vectors of int, doubles, etc.</p>
+<p>
+Suppose we have this code:</p>
+<code><pre>
+ <span class=keyword>template </span><span class=special>&lt;</span><span class=keyword>class </span><span class=identifier>T</span><span class=special>&gt;
+ </span><span class=keyword>struct </span><span class=identifier>Point
+ </span><span class=special>{
+ </span><span class=identifier>T </span><span class=identifier>x</span><span class=special>;
+ </span><span class=identifier>T </span><span class=identifier>y</span><span class=special>;
+ };
+</span></pre></code>
+<p>
+And we want to export <tt>Point</tt>s of int and double:</p>
+<code><pre>
+ <span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
+ </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>)
+ </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Pyste will assign default names for each instantiation. In this example, those
+would be &quot;<tt>Point_int</tt>&quot; and &quot;<tt>Point_double</tt>&quot;, but most of the time users will want to
+rename the instantiations:</p>
+<code><pre>
+ <span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>) // </span><span class=identifier>renames </span><span class=identifier>the </span><span class=identifier>instantiation
+ </span><span class=identifier>double_inst </span><span class=special>= </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>) // </span><span class=identifier>another </span><span class=identifier>way </span><span class=identifier>to </span><span class=keyword>do </span><span class=identifier>the </span><span class=identifier>same
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>double_inst</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Note that you can rename, exclude, set policies, etc, in the <tt>Template</tt> object
+like you would do with a <tt>Function</tt> or a <tt>Class</tt>. This changes affect all
+<b>future</b> instantiations:</p>
+<code><pre>
+ <span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
+ </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;float&quot;</span><span class=special>, </span><span class=string>&quot;FPoint&quot;</span><span class=special>) // </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>x </span><span class=keyword>and </span><span class=identifier>y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>members
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>Point</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=string>&quot;X&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>Point</span><span class=special>.</span><span class=identifier>y</span><span class=special>, </span><span class=string>&quot;Y&quot;</span><span class=special>)
+ </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>) // </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>X </span><span class=keyword>and </span><span class=identifier>Y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>members
+ </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>) // </span><span class=identifier>also </span><span class=identifier>will </span><span class=identifier>have </span><span class=identifier>X </span><span class=keyword>and </span><span class=identifier>Y </span><span class=identifier>as </span><span class=identifier>data </span><span class=identifier>member
+</span></pre></code>
+<p>
+If you want to change a option of a particular instantiation, you can do so:</p>
+<code><pre>
+ <span class=identifier>Point </span><span class=special>= </span><span class=identifier>Template</span><span class=special>(</span><span class=string>&quot;Point&quot;</span><span class=special>, </span><span class=string>&quot;point.h&quot;</span><span class=special>)
+ </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;int&quot;</span><span class=special>, </span><span class=string>&quot;IPoint&quot;</span><span class=special>)
+ </span><span class=identifier>d_inst </span><span class=special>= </span><span class=identifier>Point</span><span class=special>(</span><span class=string>&quot;double&quot;</span><span class=special>, </span><span class=string>&quot;DPoint&quot;</span><span class=special>)
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>d_inst</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=string>&quot;X&quot;</span><span class=special>) // </span><span class=identifier>only </span><span class=identifier>DPoint </span><span class=identifier>is </span><span class=identifier>affect </span><span class=identifier>by </span><span class=keyword>this </span><span class=identifier>renames</span><span class=special>,
+ </span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>d_inst</span><span class=special>.</span><span class=identifier>y</span><span class=special>, </span><span class=string>&quot;Y&quot;</span><span class=special>) // </span><span class=identifier>IPoint </span><span class=identifier>stays </span><span class=identifier>intact
+</span></pre></code>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+<img src="theme/note.gif"></img> <b>What if my template accepts more than one type?</b>
+<br><br>
+When you want to instantiate a template with more than one type, you can pass
+either a string with the types separated by whitespace, or a list of strings
+(&quot;int double&quot; or [&quot;int&quot;, &quot;double&quot;] would both work).
+ </td>
+ </tr>
+</table>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="wrappers.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/the_interface_files.html b/libs/python/pyste/doc/the_interface_files.html
new file mode 100644
index 000000000..9c0200432
--- /dev/null
+++ b/libs/python/pyste/doc/the_interface_files.html
@@ -0,0 +1,102 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>The Interface Files</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="running_pyste.html">
+<link rel="next" href="renaming_and_excluding.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>The Interface Files</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="running_pyste.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="renaming_and_excluding.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+The interface files are the heart of Pyste. The user creates one or more
+interface files declaring the classes and functions he wants to export, and then
+invokes Pyste passing the interface files to it. Pyste then generates a single
+cpp file with <a href="../../index.html">
+Boost.Python</a> code, with all the classes and functions exported.</p>
+<p>
+Besides declaring the classes and functions, the user has a number of other
+options, like renaming e excluding classes and member functionis. Those are
+explained later on.</p>
+<a name="basics"></a><h2>Basics</h2><p>
+Suppose we have a class and some functions that we want to expose to Python
+declared in the header <tt>hello.h</tt>:</p>
+<code><pre>
+ <span class=keyword>struct </span><span class=identifier>World
+ </span><span class=special>{
+ </span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) {}
+ </span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-&gt;</span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
+ };
+
+ </span><span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
+
+ </span><span class=keyword>namespace </span><span class=identifier>test </span><span class=special>{
+
+ </span><span class=keyword>void </span><span class=identifier>show</span><span class=special>(</span><span class=identifier>choice </span><span class=identifier>c</span><span class=special>) { </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=string>&quot;value: &quot; </span><span class=special>&lt;&lt; (</span><span class=keyword>int</span><span class=special>)</span><span class=identifier>c </span><span class=special>&lt;&lt; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>; }
+
+ }
+</span></pre></code>
+<p>
+We create a file named <tt>hello.pyste</tt> and create instances of the classes
+<tt>Function</tt>, <tt>Class</tt> and <tt>Enum</tt>:</p>
+<code><pre>
+ <span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;test::show&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;World&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+ </span><span class=identifier>Enum</span><span class=special>(</span><span class=string>&quot;choice&quot;</span><span class=special>, </span><span class=string>&quot;hello.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+That will expose the class, the free function and the enum found in <tt>hello.h</tt>. </p>
+<a name="inheritance"></a><h2>Inheritance</h2><p>
+Pyste automatically generates the correct code (specifying <tt>bases&lt;&gt;</tt> in the
+<tt>class_</tt> declaration) <b>if</b> the Class() function that exports the base classes
+and their children are in the same Pyste file. If that's not the case, you have
+to indicate that there's a relationship between the Pyste files using the
+<tt>Import</tt> function specifying the other Pyste file.</p>
+<p>
+Suppose we have two classes, <tt>A</tt> and <tt>B</tt>, and A is a base class for B. We
+create two Pyste files:</p>
+<p>
+<tt>A.pyste</tt>:</p>
+<code><pre>
+ <span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;A&quot;</span><span class=special>, </span><span class=string>&quot;A.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+<tt>B.pyste</tt>:</p>
+<code><pre>
+ <span class=identifier>Import</span><span class=special>(</span><span class=string>&quot;A.pyste&quot;</span><span class=special>)
+ </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;B&quot;</span><span class=special>, </span><span class=string>&quot;B.h&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+Note that we specify that <tt>B</tt> needs to know about <tt>A</tt> to be properly exported.</p>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="running_pyste.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="renaming_and_excluding.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/doc/theme/alert.gif b/libs/python/pyste/doc/theme/alert.gif
new file mode 100644
index 000000000..270764cc5
--- /dev/null
+++ b/libs/python/pyste/doc/theme/alert.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/arrow.gif b/libs/python/pyste/doc/theme/arrow.gif
new file mode 100644
index 000000000..e33db0fb4
--- /dev/null
+++ b/libs/python/pyste/doc/theme/arrow.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/bkd.gif b/libs/python/pyste/doc/theme/bkd.gif
new file mode 100644
index 000000000..dcabcb806
--- /dev/null
+++ b/libs/python/pyste/doc/theme/bkd.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/bkd2.gif b/libs/python/pyste/doc/theme/bkd2.gif
new file mode 100644
index 000000000..b03d9ba97
--- /dev/null
+++ b/libs/python/pyste/doc/theme/bkd2.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/bulb.gif b/libs/python/pyste/doc/theme/bulb.gif
new file mode 100644
index 000000000..74f3baac4
--- /dev/null
+++ b/libs/python/pyste/doc/theme/bulb.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/bullet.gif b/libs/python/pyste/doc/theme/bullet.gif
new file mode 100644
index 000000000..da787e2ef
--- /dev/null
+++ b/libs/python/pyste/doc/theme/bullet.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/l_arr.gif b/libs/python/pyste/doc/theme/l_arr.gif
new file mode 100644
index 000000000..5b3cb1cbf
--- /dev/null
+++ b/libs/python/pyste/doc/theme/l_arr.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/l_arr_disabled.gif b/libs/python/pyste/doc/theme/l_arr_disabled.gif
new file mode 100644
index 000000000..ed58a605a
--- /dev/null
+++ b/libs/python/pyste/doc/theme/l_arr_disabled.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/note.gif b/libs/python/pyste/doc/theme/note.gif
new file mode 100644
index 000000000..bd92f0755
--- /dev/null
+++ b/libs/python/pyste/doc/theme/note.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/r_arr.gif b/libs/python/pyste/doc/theme/r_arr.gif
new file mode 100644
index 000000000..2dcdad117
--- /dev/null
+++ b/libs/python/pyste/doc/theme/r_arr.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/r_arr_disabled.gif b/libs/python/pyste/doc/theme/r_arr_disabled.gif
new file mode 100644
index 000000000..2100f78bf
--- /dev/null
+++ b/libs/python/pyste/doc/theme/r_arr_disabled.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/smiley.gif b/libs/python/pyste/doc/theme/smiley.gif
new file mode 100644
index 000000000..4c848f8fe
--- /dev/null
+++ b/libs/python/pyste/doc/theme/smiley.gif
Binary files differ
diff --git a/libs/python/pyste/doc/theme/style.css b/libs/python/pyste/doc/theme/style.css
new file mode 100644
index 000000000..643df02a9
--- /dev/null
+++ b/libs/python/pyste/doc/theme/style.css
@@ -0,0 +1,178 @@
+/*=============================================================================
+ Copyright (c) 2003 Bruno da Silva de Oliveira
+
+ 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)
+=============================================================================*/
+
+body
+{
+ background-image: url(bkd.gif);
+ background-color: #FFFFFF;
+ margin: 1em 2em 1em 2em;
+}
+
+h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; text-align: left; }
+h2 { font: 140% sans-serif; font-weight: bold; text-align: left; }
+h3 { font: 120% sans-serif; font-weight: bold; text-align: left; }
+h4 { font: bold 100% sans-serif; font-weight: bold; text-align: left; }
+h5 { font: italic 100% sans-serif; font-weight: bold; text-align: left; }
+h6 { font: small-caps 100% sans-serif; font-weight: bold; text-align: left; }
+
+pre
+{
+ border-top: gray 1pt solid;
+ border-right: gray 1pt solid;
+ border-left: gray 1pt solid;
+ border-bottom: gray 1pt solid;
+
+ padding-top: 2pt;
+ padding-right: 2pt;
+ padding-left: 2pt;
+ padding-bottom: 2pt;
+
+ display: block;
+ font-family: "courier new", courier, mono;
+ background-color: #eeeeee; font-size: small
+}
+
+code
+{
+ font-family: "Courier New", Courier, mono;
+ font-size: small
+}
+
+tt
+{
+ display: inline;
+ font-family: "Courier New", Courier, mono;
+ color: #000099;
+ font-size: small
+}
+
+p
+{
+ text-align: justify;
+ font-family: Georgia, "Times New Roman", Times, serif
+}
+
+ul
+{
+ list-style-image: url(bullet.gif);
+ font-family: Georgia, "Times New Roman", Times, serif
+}
+
+ol
+{
+ font-family: Georgia, "Times New Roman", Times, serif
+}
+
+a
+{
+ font-weight: bold;
+ color: #003366;
+ text-decoration: none;
+}
+
+a:hover { color: #8080FF; }
+
+.literal { color: #666666; font-style: italic}
+.keyword { color: #000099}
+.identifier {}
+.comment { font-style: italic; color: #990000}
+.special { color: #800040}
+.preprocessor { color: #FF0000}
+.string { font-style: italic; color: #666666}
+.copyright { color: #666666; font-size: small}
+.white_bkd { background-color: #FFFFFF}
+.dk_grey_bkd { background-color: #999999}
+.quotes { color: #666666; font-style: italic; font-weight: bold}
+
+.note_box
+{
+ display: block;
+
+ border-top: gray 1pt solid;
+ border-right: gray 1pt solid;
+ border-left: gray 1pt solid;
+ border-bottom: gray 1pt solid;
+
+ padding-right: 12pt;
+ padding-left: 12pt;
+ padding-bottom: 12pt;
+ padding-top: 12pt;
+
+ font-family: Arial, Helvetica, sans-serif;
+ background-color: #E2E9EF;
+ font-size: small; text-align: justify
+}
+
+.table_title
+{
+ background-color: #648CCA;
+
+ font-family: Verdana, Arial, Helvetica, sans-serif; color: #FFFFFF;
+ font-weight: bold
+; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
+}
+
+.table_cells
+{
+ background-color: #E2E9EF;
+
+ font-family: Geneva, Arial, Helvetica, san-serif;
+ font-size: small
+; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
+}
+
+.toc
+{
+ DISPLAY: block;
+ background-color: #E2E9EF
+ font-family: Arial, Helvetica, sans-serif;
+
+ border-top: gray 1pt solid;
+ border-left: gray 1pt solid;
+ border-bottom: gray 1pt solid;
+ border-right: gray 1pt solid;
+
+ padding-top: 24pt;
+ padding-right: 24pt;
+ padding-left: 24pt;
+ padding-bottom: 24pt;
+}
+
+.toc_title
+{
+ background-color: #648CCA;
+ padding-top: 4px;
+ padding-right: 4px;
+ padding-bottom: 4px;
+ padding-left: 4px;
+ font-family: Geneva, Arial, Helvetica, san-serif;
+ color: #FFFFFF;
+ font-weight: bold
+}
+
+.toc_cells
+{
+ background-color: #E2E9EF;
+ padding-top: 4px;
+ padding-right: 4px;
+ padding-bottom: 4px;
+ padding-left: 4px;
+ font-family: Geneva, Arial, Helvetica, san-serif;
+ font-size: small
+}
+
+div.logo
+{
+ float: right;
+}
+
+.toc_cells_L0 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
+.toc_cells_L1 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 44px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
+.toc_cells_L2 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 88px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
+.toc_cells_L3 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 122px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
+.toc_cells_L4 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 166px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
diff --git a/libs/python/pyste/doc/theme/u_arr.gif b/libs/python/pyste/doc/theme/u_arr.gif
new file mode 100644
index 000000000..ada3d6e04
--- /dev/null
+++ b/libs/python/pyste/doc/theme/u_arr.gif
Binary files differ
diff --git a/libs/python/pyste/doc/wrappers.html b/libs/python/pyste/doc/wrappers.html
new file mode 100644
index 000000000..534ae5529
--- /dev/null
+++ b/libs/python/pyste/doc/wrappers.html
@@ -0,0 +1,124 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Wrappers</title>
+<link rel="stylesheet" href="theme/style.css" type="text/css">
+<link rel="prev" href="templates.html">
+<link rel="next" href="exporting_an_entire_header.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Wrappers</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="templates.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="exporting_an_entire_header.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<p>
+Suppose you have this function:</p>
+<code><pre>
+ <span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>names</span><span class=special>();
+</span></pre></code>
+<p>
+But you don't want to <a href="../../doc/v2/faq.html#question2">
+to export std::vector&lt;std::string&gt;</a>,
+you want this function to return a python list of strings. <a href="../../index.html">
+Boost.Python</a> has
+excellent support for things like that:</p>
+<code><pre>
+ <span class=identifier>list </span><span class=identifier>names_wrapper</span><span class=special>()
+ {
+ </span><span class=identifier>list </span><span class=identifier>result</span><span class=special>;
+ // </span><span class=identifier>call </span><span class=identifier>original </span><span class=identifier>function
+ </span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>names</span><span class=special>();
+ // </span><span class=identifier>put </span><span class=identifier>all </span><span class=identifier>the </span><span class=identifier>strings </span><span class=identifier>inside </span><span class=identifier>the </span><span class=identifier>python </span><span class=identifier>list
+ </span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>string</span><span class=special>&gt;::</span><span class=identifier>iterator </span><span class=identifier>it</span><span class=special>;
+ </span><span class=keyword>for </span><span class=special>(</span><span class=identifier>it </span><span class=special>= </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(); </span><span class=identifier>it </span><span class=special>!= </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>end</span><span class=special>(); ++</span><span class=identifier>it</span><span class=special>){
+ </span><span class=identifier>result</span><span class=special>.</span><span class=identifier>append</span><span class=special>(*</span><span class=identifier>it</span><span class=special>);
+ }
+ </span><span class=keyword>return </span><span class=identifier>result</span><span class=special>;
+ }
+
+ </span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>test</span><span class=special>)
+ {
+ </span><span class=identifier>def</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, &amp;</span><span class=identifier>names_wrapper</span><span class=special>);
+ }
+</span></pre></code>
+<p>
+Nice heh? Pyste supports this mechanism too. You declare the <tt>names_wrapper</tt>
+function in a header named &quot;<tt>test_wrappers.h</tt>&quot; and in the interface file:</p>
+<code><pre>
+ <span class=identifier>Include</span><span class=special>(</span><span class=string>&quot;test_wrappers.h&quot;</span><span class=special>)
+ </span><span class=identifier>names </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
+ </span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=string>&quot;names_wrapper&quot;</span><span class=special>)
+</span></pre></code>
+<p>
+You can optionally declare the function in the interface file itself:</p>
+<code><pre>
+ <span class=identifier>names_wrapper </span><span class=special>= </span><span class=identifier>Wrapper</span><span class=special>(</span><span class=string>&quot;names_wrapper&quot;</span><span class=special>,
+ </span><span class=string>&quot;&quot;</span><span class=string>&quot;
+ list names_wrapper()
+ {
+ // code to call name() and convert the vector to a list...
+ }
+ &quot;</span><span class=string>&quot;&quot;</span><span class=special>)
+ </span><span class=identifier>names </span><span class=special>= </span><span class=identifier>Function</span><span class=special>(</span><span class=string>&quot;names&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
+ </span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=identifier>names_wrapper</span><span class=special>)
+</span></pre></code>
+<p>
+The same mechanism can be used with member functions too. Just remember that
+the first parameter of wrappers for member functions is a pointer to the
+class, as in:</p>
+<code><pre>
+ <span class=keyword>struct </span><span class=identifier>C
+ </span><span class=special>{
+ </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>names</span><span class=special>();
+ }
+
+ </span><span class=identifier>list </span><span class=identifier>names_wrapper</span><span class=special>(</span><span class=identifier>C</span><span class=special>* </span><span class=identifier>c</span><span class=special>)
+ {
+ // </span><span class=identifier>same </span><span class=identifier>as </span><span class=identifier>before</span><span class=special>, </span><span class=identifier>calling </span><span class=identifier>c</span><span class=special>-&gt;</span><span class=identifier>names</span><span class=special>() </span><span class=keyword>and </span><span class=identifier>converting </span><span class=identifier>result </span><span class=identifier>to </span><span class=identifier>a </span><span class=identifier>list
+ </span><span class=special>}
+</span></pre></code>
+<p>
+And then in the interface file:</p>
+<code><pre>
+ <span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>&quot;C&quot;</span><span class=special>, </span><span class=string>&quot;test.h&quot;</span><span class=special>)
+ </span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>names</span><span class=special>, </span><span class=string>&quot;names_wrapper&quot;</span><span class=special>)
+</span></pre></code>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="note_box">
+
+<img src="theme/note.gif"></img>Even though <a href="../../index.html">
+Boost.Python</a> accepts either a pointer or a
+reference to the class in wrappers for member functions as the first parameter,
+Pyste expects them to be a <b>pointer</b>. Doing otherwise will prevent your
+code to compile when you set a wrapper for a virtual member function.
+ </td>
+ </tr>
+</table>
+<table border="0">
+ <tr>
+ <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
+ <td width="30"><a href="templates.html"><img src="theme/l_arr.gif" border="0"></a></td>
+ <td width="20"><a href="exporting_an_entire_header.html"><img src="theme/r_arr.gif" border="0"></a></td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/index.html b/libs/python/pyste/index.html
new file mode 100644
index 000000000..953b37c12
--- /dev/null
+++ b/libs/python/pyste/index.html
@@ -0,0 +1,90 @@
+<html>
+<head>
+<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
+<title>Pyste Documentation</title>
+<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
+<link rel="next" href="doc/introduction.html">
+</head>
+<body>
+<table width="100%" height="48" border="0" cellspacing="2">
+ <tr>
+ <td><img src="../../../boost.png">
+ </td>
+ <td width="85%">
+ <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Pyste Documentation</b></font>
+ </td>
+ </tr>
+</table>
+<br>
+<table width="80%" border="0" align="center">
+ <tr>
+ <td class="toc_title">Table of contents</td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L0">
+ <a href="doc/introduction.html">Introduction</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L0">
+ <a href="doc/running_pyste.html">Running Pyste</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L0">
+ <a href="doc/the_interface_files.html">The Interface Files</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/renaming_and_excluding.html">Renaming and Excluding</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/policies.html">Policies</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/templates.html">Templates</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/wrappers.html">Wrappers</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/exporting_an_entire_header.html">Exporting An Entire Header</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/smart_pointers.html">Smart Pointers</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/global_variables.html">Global Variables</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/adding_new_methods.html">Adding New Methods</a>
+ </td>
+ </tr>
+ <tr>
+ <td class="toc_cells_L1">
+ <a href="doc/inserting_code.html">Inserting Code</a>
+ </td>
+ </tr>
+</table>
+<br>
+<hr size="1"><p class="copyright">Copyright &copy; 2003 Bruno da Silva de Oliveira<br>Copyright &copy; 2002-2003 Joel de Guzman<br><br>
+<font size="2">Distributed under
+ 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) </font> </p>
+</body>
+</html>
diff --git a/libs/python/pyste/install/pyste.py b/libs/python/pyste/install/pyste.py
new file mode 100644
index 000000000..da9262353
--- /dev/null
+++ b/libs/python/pyste/install/pyste.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+# Copyright Bruno da Silva de Oliveira 2006. Distributed under 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 Pyste import pyste
+pyste.main()
diff --git a/libs/python/pyste/install/setup.py b/libs/python/pyste/install/setup.py
new file mode 100644
index 000000000..c17039817
--- /dev/null
+++ b/libs/python/pyste/install/setup.py
@@ -0,0 +1,20 @@
+# Copyright Prabhu Ramachandran 2006. Distributed under 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 distutils.core import setup
+import sys
+
+setup (name = "Pyste",
+ version = "0.9.10",
+ description = "Pyste - Python Semi-Automatic Exporter",
+ maintainer = "Bruno da Silva de Oliveira",
+ maintainer_email = "nicodemus@globalite.com.br",
+ licence = "Boost License",
+ long_description = "Pyste is a Boost.Python code generator",
+ url = "http://www.boost.org/libs/python/pyste/index.html",
+ platforms = ['Any'],
+ packages = ['Pyste'],
+ scripts = ['pyste.py'],
+ package_dir = {'Pyste': '../src/Pyste'},
+ )
diff --git a/libs/python/pyste/src/Pyste/ClassExporter.py b/libs/python/pyste/src/Pyste/ClassExporter.py
new file mode 100644
index 000000000..decaf628e
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/ClassExporter.py
@@ -0,0 +1,918 @@
+# 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)
+
+import exporters
+from Exporter import Exporter
+from declarations import *
+from settings import *
+from policies import *
+from SingleCodeUnit import SingleCodeUnit
+from EnumExporter import EnumExporter
+from utils import makeid, enumerate
+import copy
+import exporterutils
+import re
+
+#==============================================================================
+# ClassExporter
+#==============================================================================
+class ClassExporter(Exporter):
+ 'Generates boost.python code to export a class declaration'
+
+ def __init__(self, info, parser_tail=None):
+ Exporter.__init__(self, info, parser_tail)
+ # sections of code
+ self.sections = {}
+ # template: each item in the list is an item into the class_<...>
+ # section.
+ self.sections['template'] = []
+ # constructor: each item in the list is a parameter to the class_
+ # constructor, like class_<C>(...)
+ self.sections['constructor'] = []
+ # inside: everything within the class_<> statement
+ self.sections['inside'] = []
+ # scope: items outside the class statement but within its scope.
+ # scope* s = new scope(class<>());
+ # ...
+ # delete s;
+ self.sections['scope'] = []
+ # declarations: outside the BOOST_PYTHON_MODULE macro
+ self.sections['declaration'] = []
+ self.sections['declaration-outside'] = []
+ self.sections['include'] = []
+ # a list of Constructor instances
+ self.constructors = []
+ # a list of code units, generated by nested declarations
+ self.nested_codeunits = []
+
+
+ def ScopeName(self):
+ return makeid(self.class_.FullName()) + '_scope'
+
+
+ def Name(self):
+ return self.info.name
+
+
+ def SetDeclarations(self, declarations):
+ Exporter.SetDeclarations(self, declarations)
+ if self.declarations:
+ decl = self.GetDeclaration(self.info.name)
+ if isinstance(decl, Typedef):
+ self.class_ = self.GetDeclaration(decl.type.name)
+ if not self.info.rename:
+ self.info.rename = decl.name
+ else:
+ self.class_ = decl
+ self.class_ = copy.deepcopy(self.class_)
+ else:
+ self.class_ = None
+
+
+ def ClassBases(self):
+ all_bases = []
+ for level in self.class_.hierarchy:
+ for base in level:
+ all_bases.append(base)
+ return [self.GetDeclaration(x.name) for x in all_bases]
+
+
+ def Order(self):
+ '''Return the TOTAL number of bases that this class has, including the
+ bases' bases. Do this because base classes must be instantialized
+ before the derived classes in the module definition.
+ '''
+ num_bases = len(self.ClassBases())
+ return num_bases, self.class_.FullName()
+
+
+ def Export(self, codeunit, exported_names):
+ self.InheritMethods(exported_names)
+ self.MakeNonVirtual()
+ if not self.info.exclude:
+ self.ExportBasics()
+ self.ExportBases(exported_names)
+ self.ExportConstructors()
+ self.ExportVariables()
+ self.ExportVirtualMethods(codeunit)
+ self.ExportMethods()
+ self.ExportOperators()
+ self.ExportNestedClasses(exported_names)
+ self.ExportNestedEnums(exported_names)
+ self.ExportSmartPointer()
+ self.ExportOpaquePointerPolicies()
+ self.ExportAddedCode()
+ self.Write(codeunit)
+ exported_names[self.Name()] = 1
+
+
+ def InheritMethods(self, exported_names):
+ '''Go up in the class hierarchy looking for classes that were not
+ exported yet, and then add their public members to this classes
+ members, as if they were members of this class. This allows the user to
+ just export one type and automatically get all the members from the
+ base classes.
+ '''
+ valid_members = (Method, ClassVariable, NestedClass, ClassEnumeration)
+ fullnames = [x.FullName() for x in self.class_]
+ pointers = [x.PointerDeclaration(True) for x in self.class_ if isinstance(x, Method)]
+ fullnames = dict([(x, None) for x in fullnames])
+ pointers = dict([(x, None) for x in pointers])
+ for level in self.class_.hierarchy:
+ level_exported = False
+ for base in level:
+ base = self.GetDeclaration(base.name)
+ if base.FullName() not in exported_names:
+ for member in base:
+ if type(member) in valid_members:
+ member_copy = copy.deepcopy(member)
+ member_copy.class_ = self.class_.FullName()
+ if isinstance(member_copy, Method):
+ pointer = member_copy.PointerDeclaration(True)
+ if pointer not in pointers:
+ self.class_.AddMember(member)
+ pointers[pointer] = None
+ elif member_copy.FullName() not in fullnames:
+ self.class_.AddMember(member)
+ else:
+ level_exported = True
+ if level_exported:
+ break
+ def IsValid(member):
+ return isinstance(member, valid_members) and member.visibility == Scope.public
+ self.public_members = [x for x in self.class_ if IsValid(x)]
+
+
+ def Write(self, codeunit):
+ indent = self.INDENT
+ boost_ns = namespaces.python
+ pyste_ns = namespaces.pyste
+ code = ''
+ # begin a scope for this class if needed
+ nested_codeunits = self.nested_codeunits
+ needs_scope = self.sections['scope'] or nested_codeunits
+ if needs_scope:
+ scope_name = self.ScopeName()
+ code += indent + boost_ns + 'scope* %s = new %sscope(\n' %\
+ (scope_name, boost_ns)
+ # export the template section
+ template_params = ', '.join(self.sections['template'])
+ code += indent + boost_ns + 'class_< %s >' % template_params
+ # export the constructor section
+ constructor_params = ', '.join(self.sections['constructor'])
+ code += '(%s)\n' % constructor_params
+ # export the inside section
+ in_indent = indent*2
+ for line in self.sections['inside']:
+ code += in_indent + line + '\n'
+ # write the scope section and end it
+ if not needs_scope:
+ code += indent + ';\n'
+ else:
+ code += indent + ');\n'
+ for line in self.sections['scope']:
+ code += indent + line + '\n'
+ # write the contents of the nested classes
+ for nested_unit in nested_codeunits:
+ code += '\n' + nested_unit.Section('module')
+ # close the scope
+ code += indent + 'delete %s;\n' % scope_name
+
+ # write the code to the module section in the codeunit
+ codeunit.Write('module', code + '\n')
+
+ # write the declarations to the codeunit
+ declarations = '\n'.join(self.sections['declaration'])
+ for nested_unit in nested_codeunits:
+ declarations += nested_unit.Section('declaration')
+ if declarations:
+ codeunit.Write('declaration', declarations + '\n')
+ declarations_outside = '\n'.join(self.sections['declaration-outside'])
+ if declarations_outside:
+ codeunit.Write('declaration-outside', declarations_outside + '\n')
+
+ # write the includes to the codeunit
+ includes = '\n'.join(self.sections['include'])
+ for nested_unit in nested_codeunits:
+ includes += nested_unit.Section('include')
+ if includes:
+ codeunit.Write('include', includes)
+
+
+ def Add(self, section, item):
+ 'Add the item into the corresponding section'
+ self.sections[section].append(item)
+
+
+ def ExportBasics(self):
+ '''Export the name of the class and its class_ statement.'''
+ class_name = self.class_.FullName()
+ self.Add('template', class_name)
+ name = self.info.rename or self.class_.name
+ self.Add('constructor', '"%s"' % name)
+
+
+ def ExportBases(self, exported_names):
+ 'Expose the bases of the class into the template section'
+ hierarchy = self.class_.hierarchy
+ exported = []
+ for level in hierarchy:
+ for base in level:
+ if base.visibility == Scope.public and base.name in exported_names:
+ exported.append(base.name)
+ if exported:
+ break
+ if exported:
+ code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
+ self.Add('template', code)
+
+
+ def ExportConstructors(self):
+ '''Exports all the public contructors of the class, plus indicates if the
+ class is noncopyable.
+ '''
+ py_ns = namespaces.python
+ indent = self.INDENT
+
+ def init_code(cons):
+ 'return the init<>() code for the given contructor'
+ param_list = [p.FullName() for p in cons.parameters]
+ min_params_list = param_list[:cons.minArgs]
+ max_params_list = param_list[cons.minArgs:]
+ min_params = ', '.join(min_params_list)
+ max_params = ', '.join(max_params_list)
+ init = py_ns + 'init< '
+ init += min_params
+ if max_params:
+ if min_params:
+ init += ', '
+ init += py_ns + ('optional< %s >' % max_params)
+ init += ' >()'
+ return init
+
+ constructors = [x for x in self.public_members if isinstance(x, Constructor)]
+ # don't export copy constructors if the class is abstract
+ # we could remove all constructors, but this will have the effect of
+ # inserting no_init in the declaration, which would not allow
+ # even subclasses to be instantiated.
+ self.constructors = constructors[:]
+ if self.class_.abstract:
+ for cons in constructors:
+ if cons.IsCopy():
+ constructors.remove(cons)
+ break
+
+ if not constructors:
+ # declare no_init
+ self.Add('constructor', py_ns + 'no_init')
+ else:
+ # write the constructor with less parameters to the constructor section
+ smaller = None
+ for cons in constructors:
+ if smaller is None or len(cons.parameters) < len(smaller.parameters):
+ smaller = cons
+ assert smaller is not None
+ self.Add('constructor', init_code(smaller))
+ constructors.remove(smaller)
+ # write the rest to the inside section, using def()
+ for cons in constructors:
+ code = '.def(%s)' % init_code(cons)
+ self.Add('inside', code)
+
+ # check if the class is copyable
+ if not self.class_.HasCopyConstructor() or self.class_.abstract:
+ self.Add('template', namespaces.boost + 'noncopyable')
+
+
+ def ExportVariables(self):
+ 'Export the variables of the class, both static and simple variables'
+ vars = [x for x in self.public_members if isinstance(x, Variable)]
+ for var in vars:
+ if self.info[var.name].exclude:
+ continue
+ name = self.info[var.name].rename or var.name
+ fullname = var.FullName()
+ if var.type.const:
+ def_ = '.def_readonly'
+ else:
+ def_ = '.def_readwrite'
+ code = '%s("%s", &%s)' % (def_, name, fullname)
+ self.Add('inside', code)
+
+
+ def OverloadName(self, method):
+ 'Returns the name of the overloads struct for the given method'
+ name = makeid(method.FullName())
+ overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs)
+ return name + overloads
+
+
+ def GetAddedMethods(self):
+ added_methods = self.info.__added__
+ result = []
+ if added_methods:
+ for name, rename in added_methods:
+ decl = self.GetDeclaration(name)
+ self.info[name].rename = rename
+ result.append(decl)
+ return result
+
+
+ def ExportMethods(self):
+ '''Export all the non-virtual methods of this class, plus any function
+ that is to be exported as a method'''
+
+ declared = {}
+ def DeclareOverloads(m):
+ 'Declares the macro for the generation of the overloads'
+ if (isinstance(m, Method) and m.static) or type(m) == Function:
+ func = m.FullName()
+ macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS'
+ else:
+ func = m.name
+ macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS'
+ code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m.minArgs, m.maxArgs)
+ if code not in declared:
+ declared[code] = True
+ self.Add('declaration', code)
+
+
+ def Pointer(m):
+ 'returns the correct pointer declaration for the method m'
+ # check if this method has a wrapper set for him
+ wrapper = self.info[m.name].wrapper
+ if wrapper:
+ return '&' + wrapper.FullName()
+ else:
+ return m.PointerDeclaration()
+
+ def IsExportable(m):
+ 'Returns true if the given method is exportable by this routine'
+ ignore = (Constructor, ClassOperator, Destructor)
+ return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual
+
+ methods = [x for x in self.public_members if IsExportable(x)]
+ methods.extend(self.GetAddedMethods())
+
+ staticmethods = {}
+
+ for method in methods:
+ method_info = self.info[method.name]
+
+ # skip this method if it was excluded by the user
+ if method_info.exclude:
+ continue
+
+ # rename the method if the user requested
+ name = method_info.rename or method.name
+
+ # warn the user if this method needs a policy and doesn't have one
+ method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
+
+ # check for policies
+ policy = method_info.policy or ''
+ if policy:
+ policy = ', %s%s()' % (namespaces.python, policy.Code())
+ # check for overloads
+ overload = ''
+ if method.minArgs != method.maxArgs and not method_info.wrapper:
+ # add the overloads for this method
+ DeclareOverloads(method)
+ overload_name = self.OverloadName(method)
+ overload = ', %s%s()' % (namespaces.pyste, overload_name)
+
+ # build the .def string to export the method
+ pointer = Pointer(method)
+ code = '.def("%s", %s' % (name, pointer)
+ code += policy
+ code += overload
+ code += ')'
+ self.Add('inside', code)
+ # static method
+ if isinstance(method, Method) and method.static:
+ staticmethods[name] = 1
+ # add wrapper code if this method has one
+ wrapper = method_info.wrapper
+ if wrapper and wrapper.code:
+ self.Add('declaration', wrapper.code)
+
+ # export staticmethod statements
+ for name in staticmethods:
+ code = '.staticmethod("%s")' % name
+ self.Add('inside', code)
+
+
+
+ def MakeNonVirtual(self):
+ '''Make all methods that the user indicated to no_override no more virtual, delegating their
+ export to the ExportMethods routine'''
+ for member in self.class_:
+ if type(member) == Method and member.virtual:
+ member.virtual = not self.info[member.name].no_override
+
+
+ def ExportVirtualMethods(self, codeunit):
+ # check if this class has any virtual methods
+ has_virtual_methods = False
+ for member in self.class_:
+ if type(member) == Method and member.virtual:
+ has_virtual_methods = True
+ break
+
+ holder = self.info.holder
+ if has_virtual_methods:
+ generator = _VirtualWrapperGenerator(self.class_, self.ClassBases(), self.info, codeunit)
+ if holder:
+ self.Add('template', holder(generator.FullName()))
+ else:
+ self.Add('template', generator.FullName())
+ for definition in generator.GenerateDefinitions():
+ self.Add('inside', definition)
+ self.Add('declaration', generator.GenerateVirtualWrapper(self.INDENT))
+ else:
+ if holder:
+ self.Add('template', holder(self.class_.FullName()))
+
+ # operators natively supported by boost
+ BOOST_SUPPORTED_OPERATORS = '+ - * / % ^ & ! ~ | < > == != <= >= << >> && || += -= '\
+ '*= /= %= ^= &= |= <<= >>='.split()
+ # create a map for faster lookup
+ BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS))))
+
+ # a dict of operators that are not directly supported by boost, but can be exposed
+ # simply as a function with a special name
+ BOOST_RENAME_OPERATORS = {
+ '()' : '__call__',
+ }
+
+ # converters which have a special name in python
+ # it's a map of a regular expression of the converter's result to the
+ # appropriate python name
+ SPECIAL_CONVERTERS = {
+ re.compile(r'(const)?\s*double$') : '__float__',
+ re.compile(r'(const)?\s*float$') : '__float__',
+ re.compile(r'(const)?\s*int$') : '__int__',
+ re.compile(r'(const)?\s*long$') : '__long__',
+ re.compile(r'(const)?\s*char\s*\*?$') : '__str__',
+ re.compile(r'(const)?.*::basic_string<.*>\s*(\*|\&)?$') : '__str__',
+ }
+
+
+ def ExportOperators(self):
+ 'Export all member operators and free operators related to this class'
+
+ def GetFreeOperators():
+ 'Get all the free (global) operators related to this class'
+ operators = []
+ for decl in self.declarations:
+ if isinstance(decl, Operator):
+ # check if one of the params is this class
+ for param in decl.parameters:
+ if param.name == self.class_.FullName():
+ operators.append(decl)
+ break
+ return operators
+
+ def GetOperand(param):
+ 'Returns the operand of this parameter (either "self", or "other<type>")'
+ if param.name == self.class_.FullName():
+ return namespaces.python + 'self'
+ else:
+ return namespaces.python + ('other< %s >()' % param.name)
+
+
+ def HandleSpecialOperator(operator):
+ # gatter information about the operator and its parameters
+ result_name = operator.result.name
+ param1_name = ''
+ if operator.parameters:
+ param1_name = operator.parameters[0].name
+
+ # check for str
+ ostream = 'basic_ostream'
+ is_str = result_name.find(ostream) != -1 and param1_name.find(ostream) != -1
+ if is_str:
+ namespace = namespaces.python + 'self_ns::'
+ self_ = namespaces.python + 'self'
+ return '.def(%sstr(%s))' % (namespace, self_)
+
+ # is not a special operator
+ return None
+
+
+
+ frees = GetFreeOperators()
+ members = [x for x in self.public_members if type(x) == ClassOperator]
+ all_operators = frees + members
+ operators = [x for x in all_operators if not self.info['operator'][x.name].exclude]
+
+ for operator in operators:
+ # gatter information about the operator, for use later
+ wrapper = self.info['operator'][operator.name].wrapper
+ if wrapper:
+ pointer = '&' + wrapper.FullName()
+ if wrapper.code:
+ self.Add('declaration-outside', wrapper.code)
+ else:
+ pointer = operator.PointerDeclaration()
+ rename = self.info['operator'][operator.name].rename
+
+ # check if this operator will be exported as a method
+ export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS
+
+ # check if this operator has a special representation in boost
+ special_code = HandleSpecialOperator(operator)
+ has_special_representation = special_code is not None
+
+ if export_as_method:
+ # export this operator as a normal method, renaming or using the given wrapper
+ if not rename:
+ if wrapper:
+ rename = wrapper.name
+ else:
+ rename = self.BOOST_RENAME_OPERATORS[operator.name]
+ policy = ''
+ policy_obj = self.info['operator'][operator.name].policy
+ if policy_obj:
+ policy = ', %s()' % policy_obj.Code()
+ self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy))
+
+ elif has_special_representation:
+ self.Add('inside', special_code)
+
+ elif operator.name in self.BOOST_SUPPORTED_OPERATORS:
+ # export this operator using boost's facilities
+ op = operator
+ is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\
+ isinstance(op, ClassOperator) and len(op.parameters) == 0
+ if is_unary:
+ self.Add('inside', '.def( %s%sself )' % \
+ (operator.name, namespaces.python))
+ else:
+ # binary operator
+ if len(operator.parameters) == 2:
+ left_operand = GetOperand(operator.parameters[0])
+ right_operand = GetOperand(operator.parameters[1])
+ else:
+ left_operand = namespaces.python + 'self'
+ right_operand = GetOperand(operator.parameters[0])
+ self.Add('inside', '.def( %s %s %s )' % \
+ (left_operand, operator.name, right_operand))
+
+ # export the converters.
+ # export them as simple functions with a pre-determined name
+
+ converters = [x for x in self.public_members if type(x) == ConverterOperator]
+
+ def ConverterMethodName(converter):
+ result_fullname = converter.result.FullName()
+ result_name = converter.result.name
+ for regex, method_name in self.SPECIAL_CONVERTERS.items():
+ if regex.match(result_fullname):
+ return method_name
+ else:
+ # extract the last name from the full name
+ result_name = makeid(result_name)
+ return 'to_' + result_name
+
+ for converter in converters:
+ info = self.info['operator'][converter.result.FullName()]
+ # check if this operator should be excluded
+ if info.exclude:
+ continue
+
+ special_code = HandleSpecialOperator(converter)
+ if info.rename or not special_code:
+ # export as method
+ name = info.rename or ConverterMethodName(converter)
+ pointer = converter.PointerDeclaration()
+ policy_code = ''
+ if info.policy:
+ policy_code = ', %s()' % info.policy.Code()
+ self.Add('inside', '.def("%s", %s%s)' % (name, pointer, policy_code))
+
+ elif special_code:
+ self.Add('inside', special_code)
+
+
+
+ def ExportNestedClasses(self, exported_names):
+ nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)]
+ for nested_class in nested_classes:
+ nested_info = self.info[nested_class.name]
+ nested_info.include = self.info.include
+ nested_info.name = nested_class.FullName()
+ exporter = self.__class__(nested_info)
+ exporter.SetDeclarations(self.declarations)
+ codeunit = SingleCodeUnit(None, None)
+ exporter.Export(codeunit, exported_names)
+ self.nested_codeunits.append(codeunit)
+
+
+ def ExportNestedEnums(self, exported_names):
+ nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
+ for enum in nested_enums:
+ enum_info = self.info[enum.name]
+ enum_info.include = self.info.include
+ enum_info.name = enum.FullName()
+ exporter = EnumExporter(enum_info)
+ exporter.SetDeclarations(self.declarations)
+ codeunit = SingleCodeUnit(None, None)
+ exporter.Export(codeunit, exported_names)
+ self.nested_codeunits.append(codeunit)
+
+
+ def ExportSmartPointer(self):
+ smart_ptr = self.info.smart_ptr
+ if smart_ptr:
+ class_name = self.class_.FullName()
+ smart_ptr = smart_ptr % class_name
+ self.Add('scope', '%sregister_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
+
+
+ def ExportOpaquePointerPolicies(self):
+ # check all methods for 'return_opaque_pointer' policies
+ methods = [x for x in self.public_members if isinstance(x, Method)]
+ for method in methods:
+ return_opaque_policy = return_value_policy(return_opaque_pointer)
+ if self.info[method.name].policy == return_opaque_policy:
+ macro = exporterutils.EspecializeTypeID(method.result.name)
+ if macro:
+ self.Add('declaration-outside', macro)
+
+ def ExportAddedCode(self):
+ if self.info.__code__:
+ for code in self.info.__code__:
+ self.Add('inside', code)
+
+
+#==============================================================================
+# Virtual Wrapper utils
+#==============================================================================
+
+def _ParamsInfo(m, count=None):
+ if count is None:
+ count = len(m.parameters)
+ param_names = ['p%i' % i for i in range(count)]
+ param_types = [x.FullName() for x in m.parameters[:count]]
+ params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
+ #for i, p in enumerate(m.parameters[:count]):
+ # if p.default is not None:
+ # #params[i] += '=%s' % p.default
+ # params[i] += '=%s' % (p.name + '()')
+ params = ', '.join(params)
+ return params, param_names, param_types
+
+
+class _VirtualWrapperGenerator(object):
+ 'Generates code to export the virtual methods of the given class'
+
+ def __init__(self, class_, bases, info, codeunit):
+ self.class_ = copy.deepcopy(class_)
+ self.bases = bases[:]
+ self.info = info
+ self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
+ self.virtual_methods = None
+ self._method_count = {}
+ self.codeunit = codeunit
+ self.GenerateVirtualMethods()
+
+
+ SELF = 'py_self'
+
+
+ def DefaultImplementationNames(self, method):
+ '''Returns a list of default implementations for this method, one for each
+ number of default arguments. Always returns at least one name, and return from
+ the one with most arguments to the one with the least.
+ '''
+ base_name = 'default_' + method.name
+ minArgs = method.minArgs
+ maxArgs = method.maxArgs
+ if minArgs == maxArgs:
+ return [base_name]
+ else:
+ return [base_name + ('_%i' % i) for i in range(minArgs, maxArgs+1)]
+
+
+ def Declaration(self, method, indent):
+ '''Returns a string with the declarations of the virtual wrapper and
+ its default implementations. This string must be put inside the Wrapper
+ body.
+ '''
+ pyste = namespaces.pyste
+ python = namespaces.python
+ rename = self.info[method.name].rename or method.name
+ result = method.result.FullName()
+ return_str = 'return '
+ if result == 'void':
+ return_str = ''
+ params, param_names, param_types = _ParamsInfo(method)
+ constantness = ''
+ if method.const:
+ constantness = ' const'
+
+ # call_method callback
+ decl = indent + '%s %s(%s)%s%s {\n' % (result, method.name, params, constantness, method.Exceptions())
+ param_names_str = ', '.join(param_names)
+ if param_names_str:
+ param_names_str = ', ' + param_names_str
+
+ self_str = self.SELF
+
+ decl += indent*2 + '%(return_str)s%(python)scall_method< %(result)s >' \
+ '(%(self_str)s, "%(rename)s"%(param_names_str)s);\n' % locals()
+ decl += indent + '}\n'
+
+ # default implementations (with overloading)
+ def DefaultImpl(method, param_names):
+ 'Return the body of a default implementation wrapper'
+ indent2 = indent * 2
+ wrapper = self.info[method.name].wrapper
+ if not wrapper:
+ # return the default implementation of the class
+ return indent2 + '%s%s(%s);\n' % \
+ (return_str, method.FullName(), ', '.join(param_names))
+ else:
+ if wrapper.code:
+ self.codeunit.Write('declaration-outside', wrapper.code)
+ # return a call for the wrapper
+ params = ', '.join(['this'] + param_names)
+ return indent2 + '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
+
+ if not method.abstract and method.visibility != Scope.private:
+ minArgs = method.minArgs
+ maxArgs = method.maxArgs
+ impl_names = self.DefaultImplementationNames(method)
+ for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)):
+ params, param_names, param_types = _ParamsInfo(method, argNum)
+ decl += '\n'
+ decl += indent + '%s %s(%s)%s {\n' % (result, impl_name, params, constantness)
+ decl += DefaultImpl(method, param_names)
+ decl += indent + '}\n'
+ return decl
+
+
+ def MethodDefinition(self, method):
+ '''Returns a list of lines, which should be put inside the class_
+ statement to export this method.'''
+ # dont define abstract methods
+ pyste = namespaces.pyste
+ rename = self.info[method.name].rename or method.name
+ default_names = self.DefaultImplementationNames(method)
+ class_name = self.class_.FullName()
+ wrapper_name = pyste + self.wrapper_name
+ result = method.result.FullName()
+ is_method_unique = method.is_unique
+ constantness = ''
+ if method.const:
+ constantness = ' const'
+
+ # create a list of default-impl pointers
+ minArgs = method.minArgs
+ maxArgs = method.maxArgs
+ if method.abstract:
+ default_pointers = []
+ elif is_method_unique:
+ default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
+ else:
+ default_pointers = []
+ for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
+ param_list = [x.FullName() for x in method.parameters[:argNum]]
+ params = ', '.join(param_list)
+ signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
+ default_pointer = '(%s)&%s::%s' % (signature, wrapper_name, impl_name)
+ default_pointers.append(default_pointer)
+
+ # get the pointer of the method
+ pointer = method.PointerDeclaration()
+ if method.abstract:
+ pointer = namespaces.python + ('pure_virtual(%s)' % pointer)
+
+ # warn the user if this method needs a policy and doesn't have one
+ method_info = self.info[method.name]
+ method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
+
+ # Add policy to overloaded methods also
+ policy = method_info.policy or ''
+ if policy:
+ policy = ', %s%s()' % (namespaces.python, policy.Code())
+
+ # generate the defs
+ definitions = []
+ # basic def
+ if default_pointers:
+ definitions.append('.def("%s", %s, %s%s)' % (rename, pointer, default_pointers[-1], policy))
+ for default_pointer in default_pointers[:-1]:
+ definitions.append('.def("%s", %s%s)' % (rename, default_pointer, policy))
+ else:
+ definitions.append('.def("%s", %s%s)' % (rename, pointer, policy))
+ return definitions
+
+
+ def FullName(self):
+ return namespaces.pyste + self.wrapper_name
+
+
+ def GenerateVirtualMethods(self):
+ '''To correctly export all virtual methods, we must also make wrappers
+ for the virtual methods of the bases of this class, as if the methods
+ were from this class itself.
+ This method creates the instance variable self.virtual_methods.
+ '''
+ def IsVirtual(m):
+ if type(m) is Method:
+ pure_virtual = m.abstract and m.virtual
+ virtual = m.virtual and m.visibility != Scope.private
+ return virtual or pure_virtual
+ else:
+ return False
+
+ # extract the virtual methods, avoiding duplications. The duplication
+ # must take in account the full signature without the class name, so
+ # that inherited members are correctly excluded if the subclass overrides
+ # them.
+ def MethodSig(method):
+ if method.const:
+ const = ' const'
+ else:
+ const = ''
+ if method.result:
+ result = method.result.FullName()
+ else:
+ result = ''
+ params = ', '.join([x.FullName() for x in method.parameters])
+ return '%s %s(%s)%s%s' % (
+ result, method.name, params, const, method.Exceptions())
+
+ already_added = {}
+ self.virtual_methods = []
+ for member in self.class_:
+ if IsVirtual(member):
+ already_added[MethodSig(member)] = None
+ self.virtual_methods.append(member)
+
+ for base in self.bases:
+ base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
+ for base_method in base_methods:
+ self.class_.AddMember(base_method)
+
+ all_methods = [x for x in self.class_ if IsVirtual(x)]
+
+ for member in all_methods:
+ sig = MethodSig(member)
+ if IsVirtual(member) and not sig in already_added:
+ self.virtual_methods.append(member)
+ already_added[sig] = 0
+
+
+ def Constructors(self):
+ return self.class_.Constructors(publics_only=True)
+
+
+ def GenerateDefinitions(self):
+ defs = []
+ for method in self.virtual_methods:
+ exclude = self.info[method.name].exclude
+ # generate definitions only for public methods and non-abstract methods
+ if method.visibility == Scope.public and not exclude:
+ defs.extend(self.MethodDefinition(method))
+ return defs
+
+
+ def GenerateVirtualWrapper(self, indent):
+ 'Return the wrapper for this class'
+
+ # generate the class code
+ class_name = self.class_.FullName()
+ code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
+ code += '{\n'
+ # generate constructors (with the overloads for each one)
+ for cons in self.Constructors(): # only public constructors
+ minArgs = cons.minArgs
+ maxArgs = cons.maxArgs
+ # from the min number of arguments to the max number, generate
+ # all version of the given constructor
+ cons_code = ''
+ for argNum in range(minArgs, maxArgs+1):
+ params, param_names, param_types = _ParamsInfo(cons, argNum)
+ if params:
+ params = ', ' + params
+ cons_code += indent + '%s(PyObject* %s_%s):\n' % \
+ (self.wrapper_name, self.SELF, params)
+ cons_code += indent*2 + '%s(%s), %s(%s_) {}\n\n' % \
+ (class_name, ', '.join(param_names), self.SELF, self.SELF)
+ code += cons_code
+ # generate the body
+ body = []
+ for method in self.virtual_methods:
+ if not self.info[method.name].exclude:
+ body.append(self.Declaration(method, indent))
+ body = '\n'.join(body)
+ code += body + '\n'
+ # add the self member
+ code += indent + 'PyObject* %s;\n' % self.SELF
+ code += '};\n'
+ return code
diff --git a/libs/python/pyste/src/Pyste/CodeExporter.py b/libs/python/pyste/src/Pyste/CodeExporter.py
new file mode 100644
index 000000000..382fffbd5
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/CodeExporter.py
@@ -0,0 +1,26 @@
+# 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 Exporter import Exporter
+
+#==============================================================================
+# CodeExporter
+#==============================================================================
+class CodeExporter(Exporter):
+
+ def __init__(self, info):
+ Exporter.__init__(self, info)
+
+
+ def Name(self):
+ return self.info.code
+
+
+ def Export(self, codeunit, exported_names):
+ codeunit.Write(self.info.section, self.info.code)
+
+
+ def WriteInclude(self, codeunit):
+ pass
diff --git a/libs/python/pyste/src/Pyste/CppParser.py b/libs/python/pyste/src/Pyste/CppParser.py
new file mode 100644
index 000000000..be68a448a
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/CppParser.py
@@ -0,0 +1,247 @@
+# 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 GCCXMLParser import ParseDeclarations
+import tempfile
+import shutil
+import os
+import sys
+import os.path
+import settings
+import shutil
+import shelve
+from cPickle import dump, load
+
+#==============================================================================
+# exceptions
+#==============================================================================
+class CppParserError(Exception): pass
+
+#==============================================================================
+# CppParser
+#==============================================================================
+class CppParser:
+ 'Parses a header file and returns a list of declarations'
+
+ def __init__(self, includes=None, defines=None, cache_dir=None, version=None, gccxml_path = 'gccxml'):
+ 'includes and defines ar the directives given to gcc'
+ if includes is None:
+ includes = []
+ if defines is None:
+ defines = []
+ self.includes = includes
+ self.gccxml_path = gccxml_path
+ self.defines = defines
+ self.version = version
+ #if cache_dir is None:
+ # cache_dir = tempfile.mktemp()
+ # self.delete_cache = True
+ #else:
+ # self.delete_cache = False
+ self.delete_cache = False
+ self.cache_dir = cache_dir
+ self.cache_files = []
+ self.mem_cache = {}
+ # create the cache dir
+ if cache_dir:
+ try:
+ os.makedirs(cache_dir)
+ except OSError: pass
+
+
+ def __del__(self):
+ self.Close()
+
+
+ def _IncludeParams(self, filename):
+ includes = self.includes[:]
+ filedir = os.path.dirname(filename)
+ if not filedir:
+ filedir = '.'
+ includes.insert(0, filedir)
+ includes = ['-I "%s"' % self.Unixfy(x) for x in includes]
+ return ' '.join(includes)
+
+
+ def _DefineParams(self):
+ defines = ['-D "%s"' % x for x in self.defines]
+ return ' '.join(defines)
+
+
+ def FindHeader(self, header):
+ if os.path.isfile(header):
+ return header
+ for path in self.includes:
+ filename = os.path.join(path, header)
+ if os.path.isfile(filename):
+ return filename
+ else:
+ name = os.path.basename(header)
+ raise RuntimeError, 'Header file "%s" not found!' % name
+
+
+ def AppendTail(self, filename, tail):
+ '''Creates a temporary file, appends the text tail to it, and returns
+ the filename of the file.
+ '''
+ if hasattr(tempfile, 'mkstemp'):
+ f_no, temp = tempfile.mkstemp('.h')
+ f = file(temp, 'a')
+ os.close(f_no)
+ else:
+ temp = tempfile.mktemp('.h')
+ f = file(temp, 'a')
+ f.write('#include "%s"\n\n' % os.path.abspath(filename))
+ f.write(tail)
+ f.write('\n')
+ f.close()
+ return temp
+
+
+ def Unixfy(self, path):
+ return path.replace('\\', '/')
+
+
+ def ParseWithGCCXML(self, header, tail):
+ '''Parses the given header using gccxml and GCCXMLParser.
+ '''
+ header = self.FindHeader(header)
+ if tail:
+ filename = self.AppendTail(header, tail)
+ else:
+ filename = header
+ xmlfile = tempfile.mktemp('.xml')
+ try:
+ # get the params
+ includes = self._IncludeParams(filename)
+ defines = self._DefineParams()
+ # call gccxml
+ cmd = '%s %s %s "%s" -fxml=%s'
+ filename = self.Unixfy(filename)
+ xmlfile = self.Unixfy(xmlfile)
+ status = os.system(cmd % (self.gccxml_path, includes, defines, filename, xmlfile))
+ if status != 0 or not os.path.isfile(xmlfile):
+ raise CppParserError, 'Error executing gccxml'
+ # parse the resulting xml
+ declarations = ParseDeclarations(xmlfile)
+ # make the declarations' location to point to the original file
+ if tail:
+ for decl in declarations:
+ decl_filename = os.path.normpath(os.path.normcase(decl.location[0]))
+ filename = os.path.normpath(os.path.normcase(filename))
+ if decl_filename == filename:
+ decl.location = header, decl.location[1]
+ # return the declarations
+ return declarations
+ finally:
+ if settings.DEBUG and os.path.isfile(xmlfile):
+ debugname = os.path.basename(header)
+ debugname = os.path.splitext(debugname)[0] + '.xml'
+ print 'DEBUG:', debugname
+ shutil.copy(xmlfile, debugname)
+ # delete the temporary files
+ try:
+ os.remove(xmlfile)
+ if tail:
+ os.remove(filename)
+ except OSError: pass
+
+
+ def Parse(self, header, interface, tail=None):
+ '''Parses the given filename related to the given interface and returns
+ the (declarations, headerfile). The header returned is normally the
+ same as the given to this method (except that it is the full path),
+ except if tail is not None: in this case, the header is copied to a temp
+ filename and the tail code is appended to it before being passed on to
+ gccxml. This temp filename is then returned.
+ '''
+ if tail is None:
+ tail = ''
+ tail = tail.strip()
+ declarations = self.GetCache(header, interface, tail)
+ if declarations is None:
+ declarations = self.ParseWithGCCXML(header, tail)
+ self.CreateCache(header, interface, tail, declarations)
+ header_fullpath = os.path.abspath(self.FindHeader(header))
+ return declarations, header_fullpath
+
+
+ def CacheFileName(self, interface):
+ interface_name = os.path.basename(interface)
+ cache_file = os.path.splitext(interface_name)[0] + '.pystec'
+ cache_file = os.path.join(self.cache_dir, cache_file)
+ return cache_file
+
+
+ def GetCache(self, header, interface, tail):
+ key = (header, interface, tail)
+ # try memory cache first
+ if key in self.mem_cache:
+ return self.mem_cache[key]
+
+ # get the cache from the disk
+ if self.cache_dir is None:
+ return None
+ header = self.FindHeader(header)
+ cache_file = self.CacheFileName(interface)
+ if os.path.isfile(cache_file):
+ f = file(cache_file, 'rb')
+ try:
+ version = load(f)
+ if version != self.version:
+ return None
+ cache = load(f)
+ if cache.has_key(key):
+ self.cache_files.append(cache_file)
+ return cache[key]
+ else:
+ return None
+ finally:
+ f.close()
+ else:
+ return None
+
+
+ def CreateCache(self, header, interface, tail, declarations):
+ key = (header, interface, tail)
+
+ # our memory cache only holds one item
+ self.mem_cache.clear()
+ self.mem_cache[key] = declarations
+
+ # save the cache in the disk
+ if self.cache_dir is None:
+ return
+ header = self.FindHeader(header)
+ cache_file = self.CacheFileName(interface)
+ if os.path.isfile(cache_file):
+ f = file(cache_file, 'rb')
+ try:
+ version = load(f)
+ cache = load(f)
+ finally:
+ f.close()
+ else:
+ cache = {}
+ cache[key] = declarations
+ self.cache_files.append(cache_file)
+ f = file(cache_file, 'wb')
+ try:
+ dump(self.version, f, 1)
+ dump(cache, f, 1)
+ finally:
+ f.close()
+ return cache_file
+
+
+ def Close(self):
+ if self.delete_cache and self.cache_files:
+ for filename in self.cache_files:
+ try:
+ os.remove(filename)
+ except OSError:
+ pass
+ self.cache_files = []
+ shutil.rmtree(self.cache_dir)
diff --git a/libs/python/pyste/src/Pyste/EnumExporter.py b/libs/python/pyste/src/Pyste/EnumExporter.py
new file mode 100644
index 000000000..0107fbee3
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/EnumExporter.py
@@ -0,0 +1,58 @@
+# 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 Exporter import Exporter
+from settings import *
+import utils
+
+#==============================================================================
+# EnumExporter
+#==============================================================================
+class EnumExporter(Exporter):
+ 'Exports enumerators'
+
+ def __init__(self, info):
+ Exporter.__init__(self, info)
+
+
+ def SetDeclarations(self, declarations):
+ Exporter.SetDeclarations(self, declarations)
+ if self.declarations:
+ self.enum = self.GetDeclaration(self.info.name)
+ else:
+ self.enum = None
+
+ def Export(self, codeunit, exported_names):
+ if self.info.exclude:
+ return
+ indent = self.INDENT
+ in_indent = self.INDENT*2
+ rename = self.info.rename or self.enum.name
+ full_name = self.enum.FullName()
+ unnamed_enum = False
+ if rename.startswith('$_') or rename.startswith('._'):
+ unnamed_enum = True
+ code = ''
+ if not unnamed_enum:
+ code += indent + namespaces.python
+ code += 'enum_< %s >("%s")\n' % (full_name, rename)
+ for name in self.enum.values:
+ rename = self.info[name].rename or name
+ value_fullname = self.enum.ValueFullName(name)
+ if not unnamed_enum:
+ code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
+ else:
+ code += indent + namespaces.python
+ code += 'scope().attr("%s") = (int)%s;\n' % (rename, value_fullname )
+ if self.info.export_values and not unnamed_enum:
+ code += in_indent + '.export_values()\n'
+ if not unnamed_enum:
+ code += indent + ';\n'
+ code += '\n'
+ codeunit.Write('module', code)
+ exported_names[self.enum.FullName()] = 1
+
+ def Name(self):
+ return self.info.name
diff --git a/libs/python/pyste/src/Pyste/Exporter.py b/libs/python/pyste/src/Pyste/Exporter.py
new file mode 100644
index 000000000..d87b37c58
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/Exporter.py
@@ -0,0 +1,94 @@
+# 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)
+
+import os.path
+
+#==============================================================================
+# Exporter
+#==============================================================================
+class Exporter(object):
+ 'Base class for objects capable to generate boost.python code.'
+
+ INDENT = ' ' * 4
+
+ def __init__(self, info, parser_tail=None):
+ self.info = info
+ self.parser_tail = parser_tail
+ self.interface_file = None
+ self.declarations = []
+
+
+ def Name(self):
+ raise NotImplementedError(self.__class__.__name__)
+
+
+ def Tail(self):
+ return self.parser_tail
+
+
+ def Parse(self, parser):
+ self.parser = parser
+ header = self.info.include
+ tail = self.parser_tail
+ declarations, parser_header = parser.parse(header, tail)
+ self.parser_header = parser_header
+ self.SetDeclarations(declarations)
+
+
+ def SetParsedHeader(self, parsed_header):
+ self.parser_header = parsed_header
+
+
+ def SetDeclarations(self, declarations):
+ self.declarations = declarations
+
+
+ def GenerateCode(self, codeunit, exported_names):
+ self.WriteInclude(codeunit)
+ self.Export(codeunit, exported_names)
+
+
+ def WriteInclude(self, codeunit):
+ codeunit.Write('include', '#include <%s>\n' % self.info.include)
+
+
+ def Export(self, codeunit, exported_names):
+ 'subclasses must override this to do the real work'
+ pass
+
+
+ def GetDeclarations(self, fullname):
+ decls = []
+ for decl in self.declarations:
+ if decl.FullName() == fullname:
+ decls.append(decl)
+ if not decls:
+ raise RuntimeError, 'no %s declaration found!' % fullname
+ return decls
+
+
+ def GetDeclaration(self, fullname):
+ decls = self.GetDeclarations(fullname)
+ #assert len(decls) == 1
+ return decls[0]
+
+
+ def Order(self):
+ '''Returns a string that uniquely identifies this instance. All
+ exporters will be sorted by Order before being exported.
+ '''
+ return 0, self.info.name
+
+
+ def Header(self):
+ return self.info.include
+
+
+ def __eq__(self, other):
+ return type(self) is type(other) and self.Name() == other.Name() \
+ and self.interface_file == other.interface_file
+
+ def __ne__(self, other):
+ return not self == other
diff --git a/libs/python/pyste/src/Pyste/FunctionExporter.py b/libs/python/pyste/src/Pyste/FunctionExporter.py
new file mode 100644
index 000000000..5765f65e9
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/FunctionExporter.py
@@ -0,0 +1,92 @@
+# 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 Exporter import Exporter
+from policies import *
+from declarations import *
+from settings import *
+import utils
+import exporterutils
+
+
+#==============================================================================
+# FunctionExporter
+#==============================================================================
+class FunctionExporter(Exporter):
+ 'Generates boost.python code to export the given function.'
+
+ def __init__(self, info, tail=None):
+ Exporter.__init__(self, info, tail)
+
+
+ def Export(self, codeunit, exported_names):
+ if not self.info.exclude:
+ decls = self.GetDeclarations(self.info.name)
+ for decl in decls:
+ self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
+ self.ExportDeclaration(decl, len(decls) == 1, codeunit)
+ self.ExportOpaquePointer(decl, codeunit)
+ self.GenerateOverloads(decls, codeunit)
+ exported_names[self.Name()] = 1
+
+
+ def ExportDeclaration(self, decl, unique, codeunit):
+ name = self.info.rename or decl.name
+ defs = namespaces.python + 'def("%s", ' % name
+ wrapper = self.info.wrapper
+ if wrapper:
+ pointer = '&' + wrapper.FullName()
+ else:
+ pointer = decl.PointerDeclaration()
+ defs += pointer
+ defs += self.PolicyCode()
+ overload = self.OverloadName(decl)
+ if overload:
+ defs += ', %s()' % (namespaces.pyste + overload)
+ defs += ');'
+ codeunit.Write('module', self.INDENT + defs + '\n')
+ # add the code of the wrapper
+ if wrapper and wrapper.code:
+ codeunit.Write('declaration', wrapper.code + '\n')
+
+
+ def OverloadName(self, decl):
+ if decl.minArgs != decl.maxArgs:
+ return '%s_overloads_%i_%i' % \
+ (decl.name, decl.minArgs, decl.maxArgs)
+ else:
+ return ''
+
+
+ def GenerateOverloads(self, declarations, codeunit):
+ codes = {}
+ for decl in declarations:
+ overload = self.OverloadName(decl)
+ if overload and overload not in codes:
+ code = 'BOOST_PYTHON_FUNCTION_OVERLOADS(%s, %s, %i, %i)' %\
+ (overload, decl.FullName(), decl.minArgs, decl.maxArgs)
+ codeunit.Write('declaration', code + '\n')
+ codes[overload] = None
+
+
+ def PolicyCode(self):
+ policy = self.info.policy
+ if policy is not None:
+ assert isinstance(policy, Policy)
+ return ', %s()' % policy.Code()
+ else:
+ return ''
+
+
+ def ExportOpaquePointer(self, function, codeunit):
+ if self.info.policy == return_value_policy(return_opaque_pointer):
+ typename = function.result.name
+ macro = exporterutils.EspecializeTypeID(typename)
+ if macro:
+ codeunit.Write('declaration-outside', macro)
+
+
+ def Name(self):
+ return self.info.name
diff --git a/libs/python/pyste/src/Pyste/GCCXMLParser.py b/libs/python/pyste/src/Pyste/GCCXMLParser.py
new file mode 100644
index 000000000..4a1017204
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/GCCXMLParser.py
@@ -0,0 +1,478 @@
+# 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 declarations import *
+try:
+ # try to use internal elementtree
+ from xml.etree.cElementTree import ElementTree
+except ImportError:
+ # try to use cElementTree if avaiable
+ try:
+ from cElementTree import ElementTree
+ except ImportError:
+ # fall back to the normal elementtree
+ from elementtree.ElementTree import ElementTree
+from xml.parsers.expat import ExpatError
+from copy import deepcopy
+from utils import enumerate
+
+
+#==============================================================================
+# Exceptions
+#==============================================================================
+class InvalidXMLError(Exception): pass
+
+class ParserError(Exception): pass
+
+class InvalidContextError(ParserError): pass
+
+
+#==============================================================================
+# GCCXMLParser
+#==============================================================================
+class GCCXMLParser(object):
+ 'Parse a GCC_XML file and extract the top-level declarations.'
+
+ interested_tags = {'Class':0, 'Function':0, 'Variable':0, 'Enumeration':0}
+
+ def Parse(self, filename):
+ self.elements = self.GetElementsFromXML(filename)
+ # high level declarations
+ self.declarations = []
+ self._names = {}
+ # parse the elements
+ for id in self.elements:
+ element, decl = self.elements[id]
+ if decl is None:
+ try:
+ self.ParseElement(id, element)
+ except InvalidContextError:
+ pass # ignore those nodes with invalid context
+ # (workaround gccxml bug)
+
+
+ def Declarations(self):
+ return self.declarations
+
+
+ def AddDecl(self, decl):
+ if decl.FullName() in self._names:
+ decl.is_unique= False
+ for d in self.declarations:
+ if d.FullName() == decl.FullName():
+ d.is_unique = False
+ self._names[decl.FullName()] = 0
+ self.declarations.append(decl)
+
+
+ def ParseElement(self, id, element):
+ method = 'Parse' + element.tag
+ if hasattr(self, method):
+ func = getattr(self, method)
+ func(id, element)
+ else:
+ self.ParseUnknown(id, element)
+
+
+ def GetElementsFromXML(self,filename):
+ 'Extracts a dictionary of elements from the gcc_xml file.'
+
+ tree = ElementTree()
+ try:
+ tree.parse(filename)
+ except ExpatError:
+ raise InvalidXMLError, 'Not a XML file: %s' % filename
+
+ root = tree.getroot()
+ if root.tag != 'GCC_XML':
+ raise InvalidXMLError, 'Not a valid GCC_XML file'
+
+ # build a dictionary of id -> element, None
+ elementlist = root.getchildren()
+ elements = {}
+ for element in elementlist:
+ id = element.get('id')
+ if id:
+ elements[id] = element, None
+ return elements
+
+
+ def GetDecl(self, id):
+ if id not in self.elements:
+ if id == '_0':
+ raise InvalidContextError, 'Invalid context found in the xml file.'
+ else:
+ msg = 'ID not found in elements: %s' % id
+ raise ParserError, msg
+
+ elem, decl = self.elements[id]
+ if decl is None:
+ self.ParseElement(id, elem)
+ elem, decl = self.elements[id]
+ if decl is None:
+ raise ParserError, 'Could not parse element: %s' % elem.tag
+ return decl
+
+
+ def GetType(self, id):
+ def Check(id, feature):
+ pos = id.find(feature)
+ if pos != -1:
+ id = id[:pos] + id[pos+1:]
+ return True, id
+ else:
+ return False, id
+ const, id = Check(id, 'c')
+ volatile, id = Check(id, 'v')
+ restricted, id = Check(id, 'r')
+ decl = self.GetDecl(id)
+ if isinstance(decl, Type):
+ res = deepcopy(decl)
+ if const:
+ res.const = const
+ if volatile:
+ res.volatile = volatile
+ if restricted:
+ res.restricted = restricted
+ else:
+ res = Type(decl.FullName(), const)
+ res.volatile = volatile
+ res.restricted = restricted
+ return res
+
+
+ def GetLocation(self, location):
+ file, line = location.split(':')
+ file = self.GetDecl(file)
+ return file, int(line)
+
+
+ def Update(self, id, decl):
+ element, _ = self.elements[id]
+ self.elements[id] = element, decl
+
+
+ def ParseUnknown(self, id, element):
+ name = '__Unknown_Element_%s' % id
+ decl = Unknown(name)
+ self.Update(id, decl)
+
+
+ def ParseNamespace(self, id, element):
+ namespace = element.get('name')
+ context = element.get('context')
+ if context:
+ outer = self.GetDecl(context)
+ if not outer.endswith('::'):
+ outer += '::'
+ namespace = outer + namespace
+ if namespace.startswith('::'):
+ namespace = namespace[2:]
+ self.Update(id, namespace)
+
+
+ def ParseFile(self, id, element):
+ filename = element.get('name')
+ self.Update(id, filename)
+
+
+ def ParseVariable(self, id, element):
+ # in gcc_xml, a static Field is declared as a Variable, so we check
+ # this and call the Field parser.
+ context = self.GetDecl(element.get('context'))
+ if isinstance(context, Class):
+ self.ParseField(id, element)
+ elem, decl = self.elements[id]
+ decl.static = True
+ else:
+ namespace = context
+ name = element.get('name')
+ type_ = self.GetType(element.get('type'))
+ location = self.GetLocation(element.get('location'))
+ variable = Variable(type_, name, namespace)
+ variable.location = location
+ self.AddDecl(variable)
+ self.Update(id, variable)
+
+
+ def GetArguments(self, element):
+ args = []
+ for child in element:
+ if child.tag == 'Argument':
+ type = self.GetType(child.get('type'))
+ type.default = child.get('default')
+ args.append(type)
+ return args
+
+
+ def GetExceptions(self, exception_list):
+ if exception_list is None:
+ return None
+
+ exceptions = []
+ for t in exception_list.split():
+ exceptions.append(self.GetType(t))
+
+ return exceptions
+
+
+ def ParseFunction(self, id, element, functionType=Function):
+ '''functionType is used because a Operator is identical to a normal
+ function, only the type of the function changes.'''
+ name = element.get('name')
+ returns = self.GetType(element.get('returns'))
+ namespace = self.GetDecl(element.get('context'))
+ location = self.GetLocation(element.get('location'))
+ params = self.GetArguments(element)
+ incomplete = bool(int(element.get('incomplete', 0)))
+ throws = self.GetExceptions(element.get('throw', None))
+ function = functionType(name, namespace, returns, params, throws)
+ function.location = location
+ self.AddDecl(function)
+ self.Update(id, function)
+
+
+ def ParseOperatorFunction(self, id, element):
+ self.ParseFunction(id, element, Operator)
+
+
+ def GetHierarchy(self, bases):
+ '''Parses the string "bases" from the xml into a list of tuples of Base
+ instances. The first tuple is the most direct inheritance, and then it
+ goes up in the hierarchy.
+ '''
+
+ if bases is None:
+ return []
+ base_names = bases.split()
+ this_level = []
+ next_levels = []
+ for base in base_names:
+ # get the visibility
+ split = base.split(':')
+ if len(split) == 2:
+ visib = split[0]
+ base = split[1]
+ else:
+ visib = Scope.public
+ decl = self.GetDecl(base)
+ if not isinstance(decl, Class):
+ # on windows, there are some classes which "bases" points to an
+ # "Unimplemented" tag, but we are not interested in this classes
+ # anyway
+ continue
+ base = Base(decl.FullName(), visib)
+ this_level.append(base)
+ # normalize with the other levels
+ for index, level in enumerate(decl.hierarchy):
+ if index < len(next_levels):
+ next_levels[index] = next_levels[index] + level
+ else:
+ next_levels.append(level)
+ hierarchy = []
+ if this_level:
+ hierarchy.append(tuple(this_level))
+ if next_levels:
+ hierarchy.extend(next_levels)
+ return hierarchy
+
+
+ def GetMembers(self, member_list):
+ # members must be a string with the ids of the members
+ if member_list is None:
+ return []
+ members = []
+ for member in member_list.split():
+ decl = self.GetDecl(member)
+ if type(decl) in Class.ValidMemberTypes():
+ members.append(decl)
+ return members
+
+
+ def ParseClass(self, id, element):
+ name = element.get('name')
+ abstract = bool(int(element.get('abstract', '0')))
+ location = self.GetLocation(element.get('location'))
+ context = self.GetDecl(element.get('context'))
+ incomplete = bool(int(element.get('incomplete', 0)))
+ if isinstance(context, str):
+ class_ = Class(name, context, [], abstract)
+ else:
+ # a nested class
+ visib = element.get('access', Scope.public)
+ class_ = NestedClass(
+ name, context.FullName(), visib, [], abstract)
+ class_.incomplete = incomplete
+ # we have to add the declaration of the class before trying
+ # to parse its members and bases, to avoid recursion.
+ self.AddDecl(class_)
+ class_.location = location
+ self.Update(id, class_)
+ # now we can get the members and the bases
+ class_.hierarchy = self.GetHierarchy(element.get('bases'))
+ if class_.hierarchy:
+ class_.bases = class_.hierarchy[0]
+ members = self.GetMembers(element.get('members'))
+ for member in members:
+ class_.AddMember(member)
+
+
+ def ParseStruct(self, id, element):
+ self.ParseClass(id, element)
+
+
+ FUNDAMENTAL_RENAME = {
+ 'long long int' : 'boost::int64_t',
+ 'long long unsigned int' : 'boost::uint64_t',
+ }
+
+ def ParseFundamentalType(self, id, element):
+ name = element.get('name')
+ name = self.FUNDAMENTAL_RENAME.get(name, name)
+ type_ = FundamentalType(name)
+ self.Update(id, type_)
+
+
+ def ParseArrayType(self, id, element):
+ type = self.GetType(element.get('type'))
+ min = element.get('min')
+ max = element.get('max')
+ array = ArrayType(type.name, type.const, min, max)
+ self.Update(id, array)
+
+
+ def ParseReferenceType(self, id, element):
+ type = self.GetType(element.get('type'))
+ expand = not isinstance(type, FunctionType)
+ ref = ReferenceType(type.name, type.const, None, expand, type.suffix)
+ self.Update(id, ref)
+
+
+ def ParsePointerType(self, id, element):
+ type = self.GetType(element.get('type'))
+ expand = not isinstance(type, FunctionType)
+ ref = PointerType(type.name, type.const, None, expand, type.suffix)
+ self.Update(id, ref)
+
+
+ def ParseFunctionType(self, id, element):
+ result = self.GetType(element.get('returns'))
+ args = self.GetArguments(element)
+ func = FunctionType(result, args)
+ self.Update(id, func)
+
+
+ def ParseMethodType(self, id, element):
+ class_ = self.GetDecl(element.get('basetype')).FullName()
+ result = self.GetType(element.get('returns'))
+ args = self.GetArguments(element)
+ method = MethodType(result, args, class_)
+ self.Update(id, method)
+
+
+ def ParseField(self, id, element):
+ name = element.get('name')
+ visib = element.get('access', Scope.public)
+ classname = self.GetDecl(element.get('context')).FullName()
+ type_ = self.GetType(element.get('type'))
+ static = bool(int(element.get('extern', '0')))
+ location = self.GetLocation(element.get('location'))
+ var = ClassVariable(type_, name, classname, visib, static)
+ var.location = location
+ self.Update(id, var)
+
+
+ def ParseMethod(self, id, element, methodType=Method):
+ name = element.get('name')
+ result = self.GetType(element.get('returns'))
+ classname = self.GetDecl(element.get('context')).FullName()
+ visib = element.get('access', Scope.public)
+ static = bool(int(element.get('static', '0')))
+ virtual = bool(int(element.get('virtual', '0')))
+ abstract = bool(int(element.get('pure_virtual', '0')))
+ const = bool(int(element.get('const', '0')))
+ location = self.GetLocation(element.get('location'))
+ throws = self.GetExceptions(element.get('throw', None))
+ params = self.GetArguments(element)
+ method = methodType(
+ name, classname, result, params, visib, virtual, abstract, static, const, throws)
+ method.location = location
+ self.Update(id, method)
+
+
+ def ParseOperatorMethod(self, id, element):
+ self.ParseMethod(id, element, ClassOperator)
+
+
+ def ParseConstructor(self, id, element):
+ name = element.get('name')
+ visib = element.get('access', Scope.public)
+ classname = self.GetDecl(element.get('context')).FullName()
+ location = self.GetLocation(element.get('location'))
+ params = self.GetArguments(element)
+ artificial = element.get('artificial', False)
+ ctor = Constructor(name, classname, params, visib)
+ ctor.location = location
+ self.Update(id, ctor)
+
+
+ def ParseDestructor(self, id, element):
+ name = element.get('name')
+ visib = element.get('access', Scope.public)
+ classname = self.GetDecl(element.get('context')).FullName()
+ virtual = bool(int(element.get('virtual', '0')))
+ location = self.GetLocation(element.get('location'))
+ des = Destructor(name, classname, visib, virtual)
+ des.location = location
+ self.Update(id, des)
+
+
+ def ParseConverter(self, id, element):
+ self.ParseMethod(id, element, ConverterOperator)
+
+
+ def ParseTypedef(self, id, element):
+ name = element.get('name')
+ type = self.GetType(element.get('type'))
+ context = self.GetDecl(element.get('context'))
+ if isinstance(context, Class):
+ context = context.FullName()
+ typedef = Typedef(type, name, context)
+ self.Update(id, typedef)
+ self.AddDecl(typedef)
+
+
+ def ParseEnumeration(self, id, element):
+ name = element.get('name')
+ location = self.GetLocation(element.get('location'))
+ context = self.GetDecl(element.get('context'))
+ incomplete = bool(int(element.get('incomplete', 0)))
+ if isinstance(context, str):
+ enum = Enumeration(name, context)
+ else:
+ visib = element.get('access', Scope.public)
+ enum = ClassEnumeration(name, context.FullName(), visib)
+ self.AddDecl(enum)
+ enum.location = location
+ for child in element:
+ if child.tag == 'EnumValue':
+ name = child.get('name')
+ value = int(child.get('init'))
+ enum.values[name] = value
+ enum.incomplete = incomplete
+ self.Update(id, enum)
+
+
+
+def ParseDeclarations(filename):
+ 'Returns a list of the top declarations found in the gcc_xml file.'
+
+ parser = GCCXMLParser()
+ parser.Parse(filename)
+ return parser.Declarations()
+
+
+if __name__ == '__main__':
+ ParseDeclarations(r'D:\Programming\Libraries\boost-cvs\boost\libs\python\pyste\example\test.xml')
diff --git a/libs/python/pyste/src/Pyste/HeaderExporter.py b/libs/python/pyste/src/Pyste/HeaderExporter.py
new file mode 100644
index 000000000..47651ba70
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/HeaderExporter.py
@@ -0,0 +1,81 @@
+# 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 Exporter import Exporter
+from ClassExporter import ClassExporter
+from FunctionExporter import FunctionExporter
+from EnumExporter import EnumExporter
+from VarExporter import VarExporter
+from infos import *
+from declarations import *
+import os.path
+import exporters
+import MultipleCodeUnit
+
+#==============================================================================
+# HeaderExporter
+#==============================================================================
+class HeaderExporter(Exporter):
+ 'Exports all declarations found in the given header'
+
+ def __init__(self, info, parser_tail=None):
+ Exporter.__init__(self, info, parser_tail)
+
+
+ def WriteInclude(self, codeunit):
+ pass
+
+
+ def IsInternalName(self, name):
+ '''Returns true if the given name looks like a internal compiler
+ structure'''
+ return name.startswith('_')
+
+
+ def Export(self, codeunit, exported_names):
+ header = os.path.normpath(self.parser_header)
+ for decl in self.declarations:
+ # check if this declaration is in the header
+ location = os.path.abspath(decl.location[0])
+ if location == header and not self.IsInternalName(decl.name):
+ # ok, check the type of the declaration and export it accordingly
+ self.HandleDeclaration(decl, codeunit, exported_names)
+
+
+ def HandleDeclaration(self, decl, codeunit, exported_names):
+ '''Dispatch the declaration to the appropriate method, that must create
+ a suitable info object for a Exporter, create a Exporter, set its
+ declarations and append it to the list of exporters.
+ '''
+ dispatch_table = {
+ Class : ClassExporter,
+ Enumeration : EnumExporter,
+ Function : FunctionExporter,
+ Variable : VarExporter,
+ }
+
+ exporter_class = dispatch_table.get(type(decl))
+ if exporter_class is not None:
+ self.HandleExporter(decl, exporter_class, codeunit, exported_names)
+
+
+ def HandleExporter(self, decl, exporter_type, codeunit, exported_names):
+ # only export complete declarations
+ if not decl.incomplete:
+ info = self.info[decl.name]
+ info.name = decl.FullName()
+ info.include = self.info.include
+ exporter = exporter_type(info)
+ exporter.SetDeclarations(self.declarations)
+ exporter.SetParsedHeader(self.parser_header)
+ if isinstance(codeunit, MultipleCodeUnit.MultipleCodeUnit):
+ codeunit.SetCurrent(self.interface_file, exporter.Name())
+ else:
+ codeunit.SetCurrent(exporter.Name())
+ exporter.GenerateCode(codeunit, exported_names)
+
+
+ def Name(self):
+ return self.info.include
diff --git a/libs/python/pyste/src/Pyste/MultipleCodeUnit.py b/libs/python/pyste/src/Pyste/MultipleCodeUnit.py
new file mode 100644
index 000000000..65faad45d
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/MultipleCodeUnit.py
@@ -0,0 +1,135 @@
+# 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')
+
+
+
diff --git a/libs/python/pyste/src/Pyste/SingleCodeUnit.py b/libs/python/pyste/src/Pyste/SingleCodeUnit.py
new file mode 100644
index 000000000..2e59dbb80
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/SingleCodeUnit.py
@@ -0,0 +1,121 @@
+# 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 settings import namespaces
+import settings
+from utils import remove_duplicated_lines, left_equals
+from SmartFile import SmartFile
+
+
+#==============================================================================
+# SingleCodeUnit
+#==============================================================================
+class SingleCodeUnit:
+ '''
+ Represents a cpp file, where other objects can write in one of the
+ predefined sections.
+ The avaiable sections are:
+ pchinclude - The pre-compiled header area
+ include - The include area of the cpp file
+ declaration - The part before the module definition
+ module - Inside the BOOST_PYTHON_MODULE macro
+ '''
+
+ def __init__(self, modulename, filename):
+ self.modulename = modulename
+ self.filename = filename
+ # define the avaiable sections
+ self.code = {}
+ # include section
+ self.code['pchinclude'] = ''
+ # include section
+ self.code['include'] = ''
+ # declaration section (inside namespace)
+ self.code['declaration'] = ''
+ # declaration (outside namespace)
+ self.code['declaration-outside'] = ''
+ # inside BOOST_PYTHON_MACRO
+ self.code['module'] = ''
+ # create the default module definition
+ self.module_definition = 'BOOST_PYTHON_MODULE(%s)' % modulename
+
+
+ def Write(self, section, code):
+ 'write the given code in the section of the code unit'
+ if section not in self.code:
+ raise RuntimeError, 'Invalid CodeUnit section: %s' % section
+ self.code[section] += code
+
+
+ def Merge(self, other):
+ for section in ('include', 'declaration', 'declaration-outside', 'module'):
+ self.code[section] = self.code[section] + other.code[section]
+
+
+ def Section(self, section):
+ return self.code[section]
+
+
+ def SetCurrent(self, *args):
+ pass
+
+
+ def Current(self):
+ pass
+
+
+ def Save(self, append=False):
+ 'Writes this code unit to the filename'
+ space = '\n\n'
+ if not append:
+ flag = 'w'
+ else:
+ flag = 'a'
+ fout = SmartFile(self.filename, flag)
+ fout.write('\n')
+ # includes
+ # boost.python header
+ if self.code['pchinclude']:
+ fout.write(left_equals('PCH'))
+ fout.write(self.code['pchinclude']+'\n')
+ fout.write('#ifdef _MSC_VER\n')
+ fout.write('#pragma hdrstop\n')
+ fout.write('#endif\n')
+ else:
+ fout.write(left_equals('Boost Includes'))
+ fout.write('#include <boost/python.hpp>\n')
+ # include numerical boost for int64 definitions
+ fout.write('#include <boost/cstdint.hpp>\n')
+ fout.write('\n')
+ # other includes
+ if self.code['include']:
+ fout.write(left_equals('Includes'))
+ includes = remove_duplicated_lines(self.code['include'])
+ fout.write(includes)
+ fout.write(space)
+ # using
+ if settings.USING_BOOST_NS and not append:
+ fout.write(left_equals('Using'))
+ fout.write('using namespace boost::python;\n\n')
+ # declarations
+ declaration = self.code['declaration']
+ declaration_outside = self.code['declaration-outside']
+ if declaration_outside or declaration:
+ fout.write(left_equals('Declarations'))
+ if declaration_outside:
+ fout.write(declaration_outside + '\n\n')
+ if declaration:
+ pyste_namespace = namespaces.pyste[:-2]
+ fout.write('namespace %s {\n\n' % pyste_namespace)
+ fout.write(declaration)
+ fout.write('\n}// namespace %s\n' % pyste_namespace)
+ fout.write(space)
+ # module
+ fout.write(left_equals('Module'))
+ fout.write(self.module_definition + '\n')
+ fout.write('{\n')
+ fout.write(self.code['module'])
+ fout.write('}\n\n')
+ fout.close()
diff --git a/libs/python/pyste/src/Pyste/SmartFile.py b/libs/python/pyste/src/Pyste/SmartFile.py
new file mode 100644
index 000000000..039579e3b
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/SmartFile.py
@@ -0,0 +1,60 @@
+# 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)
+
+import os
+import md5
+
+#==============================================================================
+# SmartFile
+#==============================================================================
+class SmartFile(object):
+ '''
+ A file-like object used for writing files. The given file will only be
+ actually written to disk if there's not a file with the same name, or if
+ the existing file is *different* from the file to be written.
+ '''
+
+ def __init__(self, filename, mode='w'):
+ self.filename = filename
+ self.mode = mode
+ self._contents = []
+ self._closed = False
+
+
+ def __del__(self):
+ if not self._closed:
+ self.close()
+
+
+ def write(self, string):
+ self._contents.append(string)
+
+
+ def _dowrite(self, contents):
+ f = file(self.filename, self.mode)
+ f.write(contents)
+ f.close()
+
+
+ def _GetMD5(self, string):
+ return md5.new(string).digest()
+
+
+ def close(self):
+ # if the filename doesn't exist, write the file right away
+ this_contents = ''.join(self._contents)
+ if not os.path.isfile(self.filename):
+ self._dowrite(this_contents)
+ else:
+ # read the contents of the file already in disk
+ f = file(self.filename)
+ other_contents = f.read()
+ f.close()
+ # test the md5 for both files
+ this_md5 = self._GetMD5(this_contents)
+ other_md5 = self._GetMD5(other_contents)
+ if this_md5 != other_md5:
+ self._dowrite(this_contents)
+ self._closed = True
diff --git a/libs/python/pyste/src/Pyste/VarExporter.py b/libs/python/pyste/src/Pyste/VarExporter.py
new file mode 100644
index 000000000..d3571e751
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/VarExporter.py
@@ -0,0 +1,40 @@
+# 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 Exporter import Exporter
+from settings import *
+import utils
+
+#==============================================================================
+# VarExporter
+#==============================================================================
+class VarExporter(Exporter):
+ '''Exports a global variable.
+ '''
+
+ def __init__(self, info):
+ Exporter.__init__(self, info)
+
+
+ def Export(self, codeunit, exported_names):
+ if self.info.exclude: return
+ decl = self.GetDeclaration(self.info.name)
+ if not decl.type.const:
+ msg = '---> Warning: The global variable "%s" is non-const:\n' \
+ ' changes in Python will not reflect in C++.'
+ print msg % self.info.name
+ print
+ rename = self.info.rename or self.info.name
+ code = self.INDENT + namespaces.python
+ code += 'scope().attr("%s") = %s;\n' % (rename, self.info.name)
+ codeunit.Write('module', code)
+
+
+ def Order(self):
+ return 0, self.info.name
+
+
+ def Name(self):
+ return self.info.name
diff --git a/libs/python/pyste/src/Pyste/__init__.py b/libs/python/pyste/src/Pyste/__init__.py
new file mode 100644
index 000000000..02eec64b7
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/__init__.py
@@ -0,0 +1,6 @@
+# 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)
+
+
diff --git a/libs/python/pyste/src/Pyste/declarations.py b/libs/python/pyste/src/Pyste/declarations.py
new file mode 100644
index 000000000..6eff97dc5
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/declarations.py
@@ -0,0 +1,653 @@
+# 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)
+
+'''
+Defines classes that represent declarations found in C++ header files.
+
+'''
+
+# version indicates the version of the declarations. Whenever a declaration
+# changes, this variable should be updated, so that the caches can be rebuilt
+# automatically
+version = '1.0'
+
+#==============================================================================
+# Declaration
+#==============================================================================
+class Declaration(object):
+ '''Base class for all declarations.
+ @ivar name: The name of the declaration.
+ @ivar namespace: The namespace of the declaration.
+ '''
+
+ def __init__(self, name, namespace):
+ '''
+ @type name: string
+ @param name: The name of this declaration
+ @type namespace: string
+ @param namespace: the full namespace where this declaration resides.
+ '''
+ self.name = name
+ self.namespace = namespace
+ self.location = '', -1 # (filename, line)
+ self.incomplete = False
+ self.is_unique = True
+
+
+ def FullName(self):
+ '''
+ Returns the full qualified name: "boost::inner::Test"
+ @rtype: string
+ @return: The full name of the declaration.
+ '''
+ namespace = self.namespace or ''
+ if namespace and not namespace.endswith('::'):
+ namespace += '::'
+ return namespace + self.name
+
+
+ def __repr__(self):
+ return '<Declaration %s at %s>' % (self.FullName(), id(self))
+
+
+ def __str__(self):
+ return 'Declaration of %s' % self.FullName()
+
+
+#==============================================================================
+# Class
+#==============================================================================
+class Class(Declaration):
+ '''
+ Represents a C++ class or struct. Iteration through it yields its members.
+
+ @type abstract: bool
+ @ivar abstract: if the class has any abstract methods.
+
+ @type bases: tuple
+ @ivar bases: tuple with L{Base} instances, representing the most direct
+ inheritance.
+
+ @type hierarchy: list
+ @ivar hierarchy: a list of tuples of L{Base} instances, representing
+ the entire hierarchy tree of this object. The first tuple is the parent
+ classes, and the other ones go up in the hierarchy.
+ '''
+
+ def __init__(self, name, namespace, members, abstract):
+ Declaration.__init__(self, name, namespace)
+ self.__members = members
+ self.__member_names = {}
+ self.abstract = abstract
+ self.bases = ()
+ self.hierarchy = ()
+ self.operator = {}
+
+
+ def __iter__(self):
+ '''iterates through the class' members.
+ '''
+ return iter(self.__members)
+
+
+ def Constructors(self, publics_only=True):
+ '''Returns a list of the constructors for this class.
+ @rtype: list
+ '''
+ constructors = []
+ for member in self:
+ if isinstance(member, Constructor):
+ if publics_only and member.visibility != Scope.public:
+ continue
+ constructors.append(member)
+ return constructors
+
+
+ def HasCopyConstructor(self):
+ '''Returns true if this class has a public copy constructor.
+ @rtype: bool
+ '''
+ for cons in self.Constructors():
+ if cons.IsCopy():
+ return True
+ return False
+
+
+ def HasDefaultConstructor(self):
+ '''Returns true if this class has a public default constructor.
+ @rtype: bool
+ '''
+ for cons in self.Constructors():
+ if cons.IsDefault():
+ return True
+ return False
+
+
+ def AddMember(self, member):
+ if member.name in self.__member_names:
+ member.is_unique = False
+ for m in self:
+ if m.name == member.name:
+ m.is_unique = False
+ else:
+ member.is_unique = True
+ self.__member_names[member.name] = 1
+ self.__members.append(member)
+ if isinstance(member, ClassOperator):
+ self.operator[member.name] = member
+
+
+ def ValidMemberTypes():
+ return (NestedClass, Method, Constructor, Destructor, ClassVariable,
+ ClassOperator, ConverterOperator, ClassEnumeration)
+ ValidMemberTypes = staticmethod(ValidMemberTypes)
+
+
+#==============================================================================
+# NestedClass
+#==============================================================================
+class NestedClass(Class):
+ '''The declaration of a class/struct inside another class/struct.
+
+ @type class: string
+ @ivar class: fullname of the class where this class is contained.
+
+ @type visibility: L{Scope}
+ @ivar visibility: the visibility of this class.
+ '''
+
+ def __init__(self, name, class_, visib, members, abstract):
+ Class.__init__(self, name, None, members, abstract)
+ self.class_ = class_
+ self.visibility = visib
+
+
+ def FullName(self):
+ '''The full name of this class, like ns::outer::inner.
+ @rtype: string
+ '''
+ return '%s::%s' % (self.class_, self.name)
+
+
+#==============================================================================
+# Scope
+#==============================================================================
+class Scope:
+ '''Used to represent the visibility of various members inside a class.
+ @cvar public: public visibility
+ @cvar private: private visibility
+ @cvar protected: protected visibility
+ '''
+ public = 'public'
+ private = 'private'
+ protected = 'protected'
+
+
+#==============================================================================
+# Base
+#==============================================================================
+class Base:
+ '''Represents a base class of another class.
+ @ivar _name: the full name of the base class.
+ @ivar _visibility: the visibility of the derivation.
+ '''
+
+ def __init__(self, name, visibility=Scope.public):
+ self.name = name
+ self.visibility = visibility
+
+
+#==============================================================================
+# Function
+#==============================================================================
+class Function(Declaration):
+ '''The declaration of a function.
+ @ivar _result: instance of L{Type} or None.
+ @ivar _parameters: list of L{Type} instances.
+ @ivar _throws: exception specifiers or None
+ '''
+
+ def __init__(self, name, namespace, result, params, throws=None):
+ Declaration.__init__(self, name, namespace)
+ # the result type: instance of Type, or None (constructors)
+ self.result = result
+ # the parameters: instances of Type
+ self.parameters = params
+ # the exception specification
+ self.throws = throws
+
+
+ def Exceptions(self):
+ if self.throws is None:
+ return ""
+ else:
+ return " throw(%s)" % ', '.join ([x.FullName() for x in self.throws])
+
+
+ def PointerDeclaration(self, force=False):
+ '''Returns a declaration of a pointer to this function.
+ @param force: If True, returns a complete pointer declaration regardless
+ if this function is unique or not.
+ '''
+ if self.is_unique and not force:
+ return '&%s' % self.FullName()
+ else:
+ result = self.result.FullName()
+ params = ', '.join([x.FullName() for x in self.parameters])
+ return '(%s (*)(%s)%s)&%s' % (result, params, self.Exceptions(), self.FullName())
+
+
+ def MinArgs(self):
+ min = 0
+ for arg in self.parameters:
+ if arg.default is None:
+ min += 1
+ return min
+
+ minArgs = property(MinArgs)
+
+
+ def MaxArgs(self):
+ return len(self.parameters)
+
+ maxArgs = property(MaxArgs)
+
+
+
+#==============================================================================
+# Operator
+#==============================================================================
+class Operator(Function):
+ '''The declaration of a custom operator. Its name is the same as the
+ operator name in C++, ie, the name of the declaration "operator+(..)" is
+ "+".
+ '''
+
+ def FullName(self):
+ namespace = self.namespace or ''
+ if not namespace.endswith('::'):
+ namespace += '::'
+ return namespace + 'operator' + self.name
+
+
+#==============================================================================
+# Method
+#==============================================================================
+class Method(Function):
+ '''The declaration of a method.
+
+ @ivar _visibility: the visibility of this method.
+ @ivar _virtual: if this method is declared as virtual.
+ @ivar _abstract: if this method is virtual but has no default implementation.
+ @ivar _static: if this method is static.
+ @ivar _class: the full name of the class where this method was declared.
+ @ivar _const: if this method is declared as const.
+ @ivar _throws: list of exception specificiers or None
+ '''
+
+ def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const, throws=None):
+ Function.__init__(self, name, None, result, params, throws)
+ self.visibility = visib
+ self.virtual = virtual
+ self.abstract = abstract
+ self.static = static
+ self.class_ = class_
+ self.const = const
+
+
+ def FullName(self):
+ return self.class_ + '::' + self.name
+
+
+ def PointerDeclaration(self, force=False):
+ '''Returns a declaration of a pointer to this member function.
+ @param force: If True, returns a complete pointer declaration regardless
+ if this function is unique or not.
+ '''
+ if self.static:
+ # static methods are like normal functions
+ return Function.PointerDeclaration(self, force)
+ if self.is_unique and not force:
+ return '&%s' % self.FullName()
+ else:
+ result = self.result.FullName()
+ params = ', '.join([x.FullName() for x in self.parameters])
+ const = ''
+ if self.const:
+ const = 'const'
+ return '(%s (%s::*)(%s) %s%s)&%s' %\
+ (result, self.class_, params, const, self.Exceptions(), self.FullName())
+
+
+#==============================================================================
+# Constructor
+#==============================================================================
+class Constructor(Method):
+ '''A class' constructor.
+ '''
+
+ def __init__(self, name, class_, params, visib):
+ Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
+
+
+ def IsDefault(self):
+ '''Returns True if this constructor is a default constructor.
+ '''
+ return len(self.parameters) == 0 and self.visibility == Scope.public
+
+
+ def IsCopy(self):
+ '''Returns True if this constructor is a copy constructor.
+ '''
+ if len(self.parameters) != 1:
+ return False
+ param = self.parameters[0]
+ class_as_param = self.parameters[0].name == self.class_
+ param_reference = isinstance(param, ReferenceType)
+ is_public = self.visibility == Scope.public
+ return param_reference and class_as_param and param.const and is_public
+
+
+ def PointerDeclaration(self, force=False):
+ return ''
+
+
+#==============================================================================
+# Destructor
+#==============================================================================
+class Destructor(Method):
+ 'The destructor of a class.'
+
+ def __init__(self, name, class_, visib, virtual):
+ Method.__init__(self, name, class_, None, [], visib, virtual, False, False, False)
+
+ def FullName(self):
+ return self.class_ + '::~' + self.name
+
+
+ def PointerDeclaration(self, force=False):
+ return ''
+
+
+
+#==============================================================================
+# ClassOperator
+#==============================================================================
+class ClassOperator(Method):
+ 'A custom operator in a class.'
+
+ def FullName(self):
+ return self.class_ + '::operator ' + self.name
+
+
+
+#==============================================================================
+# ConverterOperator
+#==============================================================================
+class ConverterOperator(ClassOperator):
+ 'An operator in the form "operator OtherClass()".'
+
+ def FullName(self):
+ return self.class_ + '::operator ' + self.result.FullName()
+
+
+
+#==============================================================================
+# Type
+#==============================================================================
+class Type(Declaration):
+ '''Represents the type of a variable or parameter.
+ @ivar _const: if the type is constant.
+ @ivar _default: if this type has a default value associated with it.
+ @ivar _volatile: if this type was declared with the keyword volatile.
+ @ivar _restricted: if this type was declared with the keyword restricted.
+ @ivar _suffix: Suffix to get the full type name. '*' for pointers, for
+ example.
+ '''
+
+ def __init__(self, name, const=False, default=None, suffix=''):
+ Declaration.__init__(self, name, None)
+ # whatever the type is constant or not
+ self.const = const
+ # used when the Type is a function argument
+ self.default = default
+ self.volatile = False
+ self.restricted = False
+ self.suffix = suffix
+
+ def __repr__(self):
+ if self.const:
+ const = 'const '
+ else:
+ const = ''
+ return '<Type ' + const + self.name + '>'
+
+
+ def FullName(self):
+ if self.const:
+ const = 'const '
+ else:
+ const = ''
+ return const + self.name + self.suffix
+
+
+#==============================================================================
+# ArrayType
+#==============================================================================
+class ArrayType(Type):
+ '''Represents an array.
+ @ivar min: the lower bound of the array, usually 0. Can be None.
+ @ivar max: the upper bound of the array. Can be None.
+ '''
+
+ def __init__(self, name, const, min, max):
+ 'min and max can be None.'
+ Type.__init__(self, name, const)
+ self.min = min
+ self.max = max
+
+
+
+#==============================================================================
+# ReferenceType
+#==============================================================================
+class ReferenceType(Type):
+ '''A reference type.'''
+
+ def __init__(self, name, const=False, default=None, expandRef=True, suffix=''):
+ Type.__init__(self, name, const, default)
+ if expandRef:
+ self.suffix = suffix + '&'
+
+
+#==============================================================================
+# PointerType
+#==============================================================================
+class PointerType(Type):
+ 'A pointer type.'
+
+ def __init__(self, name, const=False, default=None, expandPointer=False, suffix=''):
+ Type.__init__(self, name, const, default)
+ if expandPointer:
+ self.suffix = suffix + '*'
+
+
+#==============================================================================
+# FundamentalType
+#==============================================================================
+class FundamentalType(Type):
+ 'One of the fundamental types, like int, void, etc.'
+
+ def __init__(self, name, const=False, default=None):
+ Type.__init__(self, name, const, default)
+
+
+
+#==============================================================================
+# FunctionType
+#==============================================================================
+class FunctionType(Type):
+ '''A pointer to a function.
+ @ivar _result: the return value
+ @ivar _parameters: a list of Types, indicating the parameters of the function.
+ @ivar _name: the name of the function.
+ '''
+
+ def __init__(self, result, parameters):
+ Type.__init__(self, '', False)
+ self.result = result
+ self.parameters = parameters
+ self.name = self.FullName()
+
+
+ def FullName(self):
+ full = '%s (*)' % self.result.FullName()
+ params = [x.FullName() for x in self.parameters]
+ full += '(%s)' % ', '.join(params)
+ return full
+
+
+#==============================================================================
+# MethodType
+#==============================================================================
+class MethodType(FunctionType):
+ '''A pointer to a member function of a class.
+ @ivar _class: The fullname of the class that the method belongs to.
+ '''
+
+ def __init__(self, result, parameters, class_):
+ self.class_ = class_
+ FunctionType.__init__(self, result, parameters)
+
+
+ def FullName(self):
+ full = '%s (%s::*)' % (self.result.FullName(), self.class_)
+ params = [x.FullName() for x in self.parameters]
+ full += '(%s)' % ', '.join(params)
+ return full
+
+
+#==============================================================================
+# Variable
+#==============================================================================
+class Variable(Declaration):
+ '''Represents a global variable.
+
+ @type _type: L{Type}
+ @ivar _type: The type of the variable.
+ '''
+
+ def __init__(self, type, name, namespace):
+ Declaration.__init__(self, name, namespace)
+ self.type = type
+
+
+#==============================================================================
+# ClassVariable
+#==============================================================================
+class ClassVariable(Variable):
+ '''Represents a class variable.
+
+ @type _visibility: L{Scope}
+ @ivar _visibility: The visibility of this variable within the class.
+
+ @type _static: bool
+ @ivar _static: Indicates if the variable is static.
+
+ @ivar _class: Full name of the class that this variable belongs to.
+ '''
+
+ def __init__(self, type, name, class_, visib, static):
+ Variable.__init__(self, type, name, None)
+ self.visibility = visib
+ self.static = static
+ self.class_ = class_
+
+
+ def FullName(self):
+ return self.class_ + '::' + self.name
+
+
+#==============================================================================
+# Enumeration
+#==============================================================================
+class Enumeration(Declaration):
+ '''Represents an enum.
+
+ @type _values: dict of str => int
+ @ivar _values: holds the values for this enum.
+ '''
+
+ def __init__(self, name, namespace):
+ Declaration.__init__(self, name, namespace)
+ self.values = {} # dict of str => int
+
+
+ def ValueFullName(self, name):
+ '''Returns the full name for a value in the enum.
+ '''
+ assert name in self.values
+ namespace = self.namespace
+ if namespace:
+ namespace += '::'
+ return namespace + name
+
+
+#==============================================================================
+# ClassEnumeration
+#==============================================================================
+class ClassEnumeration(Enumeration):
+ '''Represents an enum inside a class.
+
+ @ivar _class: The full name of the class where this enum belongs.
+ @ivar _visibility: The visibility of this enum inside his class.
+ '''
+
+ def __init__(self, name, class_, visib):
+ Enumeration.__init__(self, name, None)
+ self.class_ = class_
+ self.visibility = visib
+
+
+ def FullName(self):
+ return '%s::%s' % (self.class_, self.name)
+
+
+ def ValueFullName(self, name):
+ assert name in self.values
+ return '%s::%s' % (self.class_, name)
+
+
+#==============================================================================
+# Typedef
+#==============================================================================
+class Typedef(Declaration):
+ '''A Typedef declaration.
+
+ @type _type: L{Type}
+ @ivar _type: The type of the typedef.
+
+ @type _visibility: L{Scope}
+ @ivar _visibility: The visibility of this typedef.
+ '''
+
+ def __init__(self, type, name, namespace):
+ Declaration.__init__(self, name, namespace)
+ self.type = type
+ self.visibility = Scope.public
+
+
+
+
+
+#==============================================================================
+# Unknown
+#==============================================================================
+class Unknown(Declaration):
+ '''A declaration that Pyste does not know how to handle.
+ '''
+
+ def __init__(self, name):
+ Declaration.__init__(self, name, None)
diff --git a/libs/python/pyste/src/Pyste/exporters.py b/libs/python/pyste/src/Pyste/exporters.py
new file mode 100644
index 000000000..f573d01be
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/exporters.py
@@ -0,0 +1,12 @@
+# 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)
+
+
+# a list of Exporter instances
+exporters = []
+
+current_interface = None # the current interface file being processed
+importing = False # whetever we are now importing a pyste file.
+ # exporters created here shouldn't export themselves
diff --git a/libs/python/pyste/src/Pyste/exporterutils.py b/libs/python/pyste/src/Pyste/exporterutils.py
new file mode 100644
index 000000000..363700d2b
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/exporterutils.py
@@ -0,0 +1,87 @@
+# 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)
+
+'''
+Various helpers for interface files.
+'''
+
+from settings import *
+from policies import *
+from declarations import *
+
+#==============================================================================
+# FunctionWrapper
+#==============================================================================
+class FunctionWrapper(object):
+ '''Holds information about a wrapper for a function or a method. It is
+ divided in 2 parts: the name of the Wrapper, and its code. The code is
+ placed in the declaration section of the module, while the name is used to
+ def' the function or method (with the pyste namespace prepend to it). If
+ code is None, the name is left unchanged.
+ '''
+
+ def __init__(self, name, code=None):
+ self.name = name
+ self.code = code
+
+ def FullName(self):
+ if self.code:
+ return namespaces.pyste + self.name
+ else:
+ return self.name
+
+
+_printed_warnings = {} # used to avoid double-prints of warnings
+
+#==============================================================================
+# HandlePolicy
+#==============================================================================
+def HandlePolicy(function, policy):
+ '''Show a warning to the user if the function needs a policy and doesn't
+ have one. Return a policy to the function, which is the given policy itself
+ if it is not None, or a default policy for this method.
+ '''
+
+ def IsString(type):
+ 'Return True if the Type instance can be considered a string'
+ return type.FullName() == 'const char*'
+
+ def IsPyObject(type):
+ return type.FullName() == '_object *' # internal name of PyObject
+
+ result = function.result
+ # if the function returns const char*, a policy is not needed
+ if IsString(result) or IsPyObject(result):
+ return policy
+ # if returns a const T&, set the default policy
+ if policy is None and result.const and isinstance(result, ReferenceType):
+ policy = return_value_policy(copy_const_reference)
+ # basic test if the result type demands a policy
+ needs_policy = isinstance(result, (ReferenceType, PointerType))
+ # show a warning to the user, if needed
+ if needs_policy and policy is None:
+ global _printed_warnings
+ warning = '---> Error: %s returns a pointer or a reference, ' \
+ 'but no policy was specified.' % function.FullName()
+ if warning not in _printed_warnings:
+ print warning
+ print
+ # avoid double prints of the same warning
+ _printed_warnings[warning] = 1
+ return policy
+
+
+#==============================================================================
+# EspecializeTypeID
+#==============================================================================
+_exported_type_ids = {}
+def EspecializeTypeID(typename):
+ global _exported_type_ids
+ macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)\n' % typename
+ if macro not in _exported_type_ids:
+ _exported_type_ids[macro] = 1
+ return macro
+ else:
+ return None
diff --git a/libs/python/pyste/src/Pyste/infos.py b/libs/python/pyste/src/Pyste/infos.py
new file mode 100644
index 000000000..2a4f01eaf
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/infos.py
@@ -0,0 +1,259 @@
+# 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)
+
+import os.path
+import copy
+import exporters
+from ClassExporter import ClassExporter
+from FunctionExporter import FunctionExporter
+from EnumExporter import EnumExporter
+from HeaderExporter import HeaderExporter
+from VarExporter import VarExporter
+from CodeExporter import CodeExporter
+from exporterutils import FunctionWrapper
+from utils import makeid
+import warnings
+
+#==============================================================================
+# DeclarationInfo
+#==============================================================================
+class DeclarationInfo:
+
+ def __init__(self, otherInfo=None):
+ self.__infos = {}
+ self.__attributes = {}
+ if otherInfo is not None:
+ self.__infos = copy.deepcopy(otherInfo.__infos)
+ self.__attributes = copy.deepcopy(otherInfo.__attributes)
+
+
+ def __getitem__(self, name):
+ 'Used to access sub-infos'
+ if name.startswith('__'):
+ raise AttributeError
+ default = DeclarationInfo()
+ default._Attribute('name', name)
+ return self.__infos.setdefault(name, default)
+
+
+ def __getattr__(self, name):
+ return self[name]
+
+
+ def _Attribute(self, name, value=None):
+ if value is None:
+ # get value
+ return self.__attributes.get(name)
+ else:
+ # set value
+ self.__attributes[name] = value
+
+
+ def AddExporter(self, exporter):
+ # this was causing a much serious bug, as reported by Niall Douglas:
+ # another solution must be found!
+ #if not exporters.importing:
+ if exporter not in exporters.exporters:
+ exporters.exporters.append(exporter)
+ exporter.interface_file = exporters.current_interface
+
+
+#==============================================================================
+# FunctionInfo
+#==============================================================================
+class FunctionInfo(DeclarationInfo):
+
+ def __init__(self, name, include, tail=None, otherOption=None,
+ exporter_class = FunctionExporter):
+ DeclarationInfo.__init__(self, otherOption)
+ self._Attribute('name', name)
+ self._Attribute('include', include)
+ self._Attribute('exclude', False)
+ # create a FunctionExporter
+ exporter = exporter_class(InfoWrapper(self), tail)
+ self.AddExporter(exporter)
+
+
+#==============================================================================
+# ClassInfo
+#==============================================================================
+class ClassInfo(DeclarationInfo):
+
+ def __init__(self, name, include, tail=None, otherInfo=None,
+ exporter_class = ClassExporter):
+ DeclarationInfo.__init__(self, otherInfo)
+ self._Attribute('name', name)
+ self._Attribute('include', include)
+ self._Attribute('exclude', False)
+ # create a ClassExporter
+ exporter = exporter_class(InfoWrapper(self), tail)
+ self.AddExporter(exporter)
+
+
+#==============================================================================
+# templates
+#==============================================================================
+def GenerateName(name, type_list):
+ name = name.replace('::', '_')
+ names = [name] + type_list
+ return makeid('_'.join(names))
+
+
+class ClassTemplateInfo(DeclarationInfo):
+
+ def __init__(self, name, include,
+ exporter_class = ClassExporter):
+ DeclarationInfo.__init__(self)
+ self._Attribute('name', name)
+ self._Attribute('include', include)
+ self._exporter_class = exporter_class
+
+
+ def Instantiate(self, type_list, rename=None):
+ if not rename:
+ rename = GenerateName(self._Attribute('name'), type_list)
+ # generate code to instantiate the template
+ types = ', '.join(type_list)
+ tail = 'typedef %s< %s > %s;\n' % (self._Attribute('name'), types, rename)
+ tail += 'void __instantiate_%s()\n' % rename
+ tail += '{ sizeof(%s); }\n\n' % rename
+ # create a ClassInfo
+ class_ = ClassInfo(rename, self._Attribute('include'), tail, self,
+ exporter_class = self._exporter_class)
+ return class_
+
+
+ def __call__(self, types, rename=None):
+ if isinstance(types, str):
+ types = types.split()
+ return self.Instantiate(types, rename)
+
+#==============================================================================
+# EnumInfo
+#==============================================================================
+class EnumInfo(DeclarationInfo):
+
+ def __init__(self, name, include, exporter_class = EnumExporter):
+ DeclarationInfo.__init__(self)
+ self._Attribute('name', name)
+ self._Attribute('include', include)
+ self._Attribute('exclude', False)
+ self._Attribute('export_values', False)
+ exporter = exporter_class(InfoWrapper(self))
+ self.AddExporter(exporter)
+
+
+#==============================================================================
+# HeaderInfo
+#==============================================================================
+class HeaderInfo(DeclarationInfo):
+
+ def __init__(self, include, exporter_class = HeaderExporter):
+ warnings.warn('AllFromHeader is not working in all cases in the current version.')
+ DeclarationInfo.__init__(self)
+ self._Attribute('include', include)
+ exporter = exporter_class(InfoWrapper(self))
+ self.AddExporter(exporter)
+
+
+#==============================================================================
+# VarInfo
+#==============================================================================
+class VarInfo(DeclarationInfo):
+
+ def __init__(self, name, include, exporter_class = VarExporter):
+ DeclarationInfo.__init__(self)
+ self._Attribute('name', name)
+ self._Attribute('include', include)
+ exporter = exporter_class(InfoWrapper(self))
+ self.AddExporter(exporter)
+
+
+#==============================================================================
+# CodeInfo
+#==============================================================================
+class CodeInfo(DeclarationInfo):
+
+ def __init__(self, code, section, exporter_class = CodeExporter):
+ DeclarationInfo.__init__(self)
+ self._Attribute('code', code)
+ self._Attribute('section', section)
+ exporter = exporter_class(InfoWrapper(self))
+ self.AddExporter(exporter)
+
+
+#==============================================================================
+# InfoWrapper
+#==============================================================================
+class InfoWrapper:
+ 'Provides a nicer interface for a info'
+
+ def __init__(self, info):
+ self.__dict__['_info'] = info # so __setattr__ is not called
+
+ def __getitem__(self, name):
+ return InfoWrapper(self._info[name])
+
+ def __getattr__(self, name):
+ return self._info._Attribute(name)
+
+ def __setattr__(self, name, value):
+ self._info._Attribute(name, value)
+
+
+#==============================================================================
+# Functions
+#==============================================================================
+def exclude(info):
+ info._Attribute('exclude', True)
+
+def set_policy(info, policy):
+ info._Attribute('policy', policy)
+
+def rename(info, name):
+ info._Attribute('rename', name)
+
+def set_wrapper(info, wrapper):
+ if isinstance(wrapper, str):
+ wrapper = FunctionWrapper(wrapper)
+ info._Attribute('wrapper', wrapper)
+
+def instantiate(template, types, rename=None):
+ if isinstance(types, str):
+ types = types.split()
+ return template.Instantiate(types, rename)
+
+def use_shared_ptr(info):
+ info._Attribute('smart_ptr', 'boost::shared_ptr< %s >')
+
+def use_auto_ptr(info):
+ info._Attribute('smart_ptr', 'std::auto_ptr< %s >')
+
+def holder(info, function):
+ msg = "Expected a callable that accepts one string argument."
+ assert callable(function), msg
+ info._Attribute('holder', function)
+
+def add_method(info, name, rename=None):
+ added = info._Attribute('__added__')
+ if added is None:
+ info._Attribute('__added__', [(name, rename)])
+ else:
+ added.append((name, rename))
+
+
+def class_code(info, code):
+ added = info._Attribute('__code__')
+ if added is None:
+ info._Attribute('__code__', [code])
+ else:
+ added.append(code)
+
+def final(info):
+ info._Attribute('no_override', True)
+
+
+def export_values(info):
+ info._Attribute('export_values', True)
diff --git a/libs/python/pyste/src/Pyste/policies.py b/libs/python/pyste/src/Pyste/policies.py
new file mode 100644
index 000000000..57ebd0dea
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/policies.py
@@ -0,0 +1,95 @@
+# 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)
+
+
+
+class Policy(object):
+ 'Represents one of the call policies of boost.python.'
+
+ def __init__(self):
+ if type(self) is Policy:
+ raise RuntimeError, "Can't create an instance of the class Policy"
+
+
+ def Code(self):
+ 'Returns the string corresponding to a instancialization of the policy.'
+ pass
+
+
+ def _next(self):
+ if self.next is not None:
+ return ', %s >' % self.next.Code()
+ else:
+ return ' >'
+
+
+ def __eq__(self, other):
+ try:
+ return self.Code() == other.Code()
+ except AttributeError:
+ return False
+
+
+
+class return_internal_reference(Policy):
+ 'Ties the return value to one of the parameters.'
+
+ def __init__(self, param=1, next=None):
+ '''
+ param is the position of the parameter, or None for "self".
+ next indicates the next policy, or None.
+ '''
+ self.param = param
+ self.next=next
+
+
+ def Code(self):
+ c = 'return_internal_reference< %i' % self.param
+ c += self._next()
+ return c
+
+
+
+class with_custodian_and_ward(Policy):
+ 'Ties lifetime of two arguments of a function.'
+
+ def __init__(self, custodian, ward, next=None):
+ self.custodian = custodian
+ self.ward = ward
+ self.next = next
+
+ def Code(self):
+ c = 'with_custodian_and_ward< %i, %i' % (self.custodian, self.ward)
+ c += self._next()
+ return c
+
+
+
+class return_value_policy(Policy):
+ 'Policy to convert return values.'
+
+ def __init__(self, which, next=None):
+ self.which = which
+ self.next = next
+
+
+ def Code(self):
+ c = 'return_value_policy< %s' % self.which
+ c += self._next()
+ return c
+
+class return_self(Policy):
+
+ def Code(self):
+ return 'return_self<>'
+
+
+# values for return_value_policy
+reference_existing_object = 'reference_existing_object'
+copy_const_reference = 'copy_const_reference'
+copy_non_const_reference = 'copy_non_const_reference'
+manage_new_object = 'manage_new_object'
+return_opaque_pointer = 'return_opaque_pointer'
+return_by_value = 'return_by_value'
diff --git a/libs/python/pyste/src/Pyste/pyste.py b/libs/python/pyste/src/Pyste/pyste.py
new file mode 100644
index 000000000..cedffff55
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/pyste.py
@@ -0,0 +1,424 @@
+# 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)
+
+"""
+Pyste version %s
+
+Usage:
+ pyste [options] interface-files
+
+where options are:
+ --module=<name> The name of the module that will be generated;
+ defaults to the first interface filename, without
+ the extension.
+ -I <path> Add an include path
+ -D <symbol> Define symbol
+ --multiple Create various cpps, instead of only one
+ (useful during development)
+ --out=<name> Specify output filename (default: <module>.cpp)
+ in --multiple mode, this will be a directory
+ --no-using Do not declare "using namespace boost";
+ use explicit declarations instead
+ --pyste-ns=<name> Set the namespace where new types will be declared;
+ default is the empty namespace
+ --debug Writes the xml for each file parsed in the current
+ directory
+ --cache-dir=<dir> Directory for cache files (speeds up future runs)
+ --only-create-cache Recreates all caches (doesn't generate code).
+ --generate-main Generates the _main.cpp file (in multiple mode)
+ --file-list A file with one pyste file per line. Use as a
+ substitute for passing the files in the command
+ line.
+ --gccxml-path=<path> Path to gccxml executable (default: gccxml)
+ --no-default-include Do not use INCLUDE environment variable for include
+ files to pass along gccxml.
+ -h, --help Print this help and exit
+ -v, --version Print version information
+"""
+
+import sys
+import os
+import getopt
+import exporters
+import SingleCodeUnit
+import MultipleCodeUnit
+import infos
+import exporterutils
+import settings
+import gc
+import sys
+from policies import *
+from CppParser import CppParser, CppParserError
+import time
+import declarations
+
+__version__ = '0.9.30'
+
+def RecursiveIncludes(include):
+ 'Return a list containg the include dir and all its subdirectories'
+ dirs = [include]
+ def visit(arg, dir, names):
+ # ignore CVS dirs
+ if os.path.split(dir)[1] != 'CVS':
+ dirs.append(dir)
+ os.path.walk(include, visit, None)
+ return dirs
+
+
+def GetDefaultIncludes():
+ if 'INCLUDE' in os.environ:
+ include = os.environ['INCLUDE']
+ return include.split(os.pathsep)
+ else:
+ return []
+
+
+def ProcessIncludes(includes):
+ if sys.platform == 'win32':
+ index = 0
+ for include in includes:
+ includes[index] = include.replace('\\', '/')
+ index += 1
+
+
+def ReadFileList(filename):
+ f = file(filename)
+ files = []
+ try:
+ for line in f:
+ line = line.strip()
+ if line:
+ files.append(line)
+ finally:
+ f.close()
+ return files
+
+
+def ParseArguments():
+
+ def Usage():
+ print __doc__ % __version__
+ sys.exit(1)
+
+ try:
+ options, files = getopt.getopt(
+ sys.argv[1:],
+ 'R:I:D:vh',
+ ['module=', 'multiple', 'out=', 'no-using', 'pyste-ns=', 'debug', 'cache-dir=',
+ 'only-create-cache', 'version', 'generate-main', 'file-list=', 'help',
+ 'gccxml-path=', 'no-default-include'])
+ except getopt.GetoptError, e:
+ print
+ print 'ERROR:', e
+ Usage()
+
+ default_includes = GetDefaultIncludes()
+ includes = []
+ defines = []
+ module = None
+ out = None
+ multiple = False
+ cache_dir = None
+ create_cache = False
+ generate_main = False
+ gccxml_path = 'gccxml'
+
+ for opt, value in options:
+ if opt == '-I':
+ includes.append(value)
+ elif opt == '-D':
+ defines.append(value)
+ elif opt == '-R':
+ includes.extend(RecursiveIncludes(value))
+ elif opt == '--module':
+ module = value
+ elif opt == '--out':
+ out = value
+ elif opt == '--no-using':
+ settings.namespaces.python = 'boost::python::'
+ settings.USING_BOOST_NS = False
+ elif opt == '--pyste-ns':
+ settings.namespaces.pyste = value + '::'
+ elif opt == '--debug':
+ settings.DEBUG = True
+ elif opt == '--multiple':
+ multiple = True
+ elif opt == '--cache-dir':
+ cache_dir = value
+ elif opt == '--only-create-cache':
+ create_cache = True
+ elif opt == '--file-list':
+ files += ReadFileList(value)
+ elif opt in ['-h', '--help']:
+ Usage()
+ elif opt in ['-v', '--version']:
+ print 'Pyste version %s' % __version__
+ sys.exit(2)
+ elif opt == '--generate-main':
+ generate_main = True
+ elif opt == '--gccxml-path':
+ gccxml_path = value
+ elif opt == '--no-default-include':
+ default_includes = []
+ else:
+ print 'Unknown option:', opt
+ Usage()
+
+ includes[0:0] = default_includes
+ if not files:
+ Usage()
+ if not module:
+ module = os.path.splitext(os.path.basename(files[0]))[0]
+ if not out:
+ out = module
+ if not multiple:
+ out += '.cpp'
+ for file in files:
+ d = os.path.dirname(os.path.abspath(file))
+ if d not in sys.path:
+ sys.path.append(d)
+
+ if create_cache and not cache_dir:
+ print 'Error: Use --cache-dir to indicate where to create the cache files!'
+ Usage()
+ sys.exit(3)
+
+ if generate_main and not multiple:
+ print 'Error: --generate-main only valid in multiple mode.'
+ Usage()
+ sys.exit(3)
+
+ ProcessIncludes(includes)
+ return includes, defines, module, out, files, multiple, cache_dir, create_cache, \
+ generate_main, gccxml_path
+
+
+def PCHInclude(*headers):
+ code = '\n'.join(['#include <%s>' % x for x in headers])
+ infos.CodeInfo(code, 'pchinclude')
+
+
+def CreateContext():
+ 'create the context where a interface file will be executed'
+ context = {}
+ context['Import'] = Import
+ # infos
+ context['Function'] = infos.FunctionInfo
+ context['Class'] = infos.ClassInfo
+ context['Include'] = lambda header: infos.CodeInfo('#include <%s>\n' % header, 'include')
+ context['PCHInclude'] = PCHInclude
+ context['Template'] = infos.ClassTemplateInfo
+ context['Enum'] = infos.EnumInfo
+ context['AllFromHeader'] = infos.HeaderInfo
+ context['Var'] = infos.VarInfo
+ # functions
+ context['rename'] = infos.rename
+ context['set_policy'] = infos.set_policy
+ context['exclude'] = infos.exclude
+ context['set_wrapper'] = infos.set_wrapper
+ context['use_shared_ptr'] = infos.use_shared_ptr
+ context['use_auto_ptr'] = infos.use_auto_ptr
+ context['holder'] = infos.holder
+ context['add_method'] = infos.add_method
+ context['final'] = infos.final
+ context['export_values'] = infos.export_values
+ # policies
+ context['return_internal_reference'] = return_internal_reference
+ context['with_custodian_and_ward'] = with_custodian_and_ward
+ context['return_value_policy'] = return_value_policy
+ context['reference_existing_object'] = reference_existing_object
+ context['copy_const_reference'] = copy_const_reference
+ context['copy_non_const_reference'] = copy_non_const_reference
+ context['return_opaque_pointer'] = return_opaque_pointer
+ context['manage_new_object'] = manage_new_object
+ context['return_by_value'] = return_by_value
+ context['return_self'] = return_self
+ # utils
+ context['Wrapper'] = exporterutils.FunctionWrapper
+ context['declaration_code'] = lambda code: infos.CodeInfo(code, 'declaration-outside')
+ context['module_code'] = lambda code: infos.CodeInfo(code, 'module')
+ context['class_code'] = infos.class_code
+ return context
+
+
+def Begin():
+ # parse arguments
+ includes, defines, module, out, interfaces, multiple, cache_dir, create_cache, generate_main, gccxml_path = ParseArguments()
+ # run pyste scripts
+ for interface in interfaces:
+ ExecuteInterface(interface)
+ # create the parser
+ parser = CppParser(includes, defines, cache_dir, declarations.version, gccxml_path)
+ try:
+ if not create_cache:
+ if not generate_main:
+ return GenerateCode(parser, module, out, interfaces, multiple)
+ else:
+ return GenerateMain(module, out, OrderInterfaces(interfaces))
+ else:
+ return CreateCaches(parser)
+ finally:
+ parser.Close()
+
+
+def CreateCaches(parser):
+ # There is one cache file per interface so we organize the headers
+ # by interfaces. For each interface collect the tails from the
+ # exporters sharing the same header.
+ tails = JoinTails(exporters.exporters)
+
+ # now for each interface file take each header, and using the tail
+ # get the declarations and cache them.
+ for interface, header in tails:
+ tail = tails[(interface, header)]
+ declarations = parser.ParseWithGCCXML(header, tail)
+ cachefile = parser.CreateCache(header, interface, tail, declarations)
+ print 'Cached', cachefile
+
+ return 0
+
+
+_imported_count = {} # interface => count
+
+def ExecuteInterface(interface):
+ old_interface = exporters.current_interface
+ if not os.path.exists(interface):
+ if old_interface and os.path.exists(old_interface):
+ d = os.path.dirname(old_interface)
+ interface = os.path.join(d, interface)
+ if not os.path.exists(interface):
+ raise IOError, "Cannot find interface file %s."%interface
+
+ _imported_count[interface] = _imported_count.get(interface, 0) + 1
+ exporters.current_interface = interface
+ context = CreateContext()
+ context['INTERFACE_FILE'] = os.path.abspath(interface)
+ execfile(interface, context)
+ exporters.current_interface = old_interface
+
+
+def Import(interface):
+ exporters.importing = True
+ ExecuteInterface(interface)
+ exporters.importing = False
+
+
+def JoinTails(exports):
+ '''Returns a dict of {(interface, header): tail}, where tail is the
+ joining of all tails of all exports for the header.
+ '''
+ tails = {}
+ for export in exports:
+ interface = export.interface_file
+ header = export.Header()
+ tail = export.Tail() or ''
+ if (interface, header) in tails:
+ all_tails = tails[(interface,header)]
+ all_tails += '\n' + tail
+ tails[(interface, header)] = all_tails
+ else:
+ tails[(interface, header)] = tail
+
+ return tails
+
+
+
+def OrderInterfaces(interfaces):
+ interfaces_order = [(_imported_count[x], x) for x in interfaces]
+ interfaces_order.sort()
+ interfaces_order.reverse()
+ return [x for _, x in interfaces_order]
+
+
+
+def GenerateMain(module, out, interfaces):
+ codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
+ codeunit.GenerateMain(interfaces)
+ return 0
+
+
+def GenerateCode(parser, module, out, interfaces, multiple):
+ # prepare to generate the wrapper code
+ if multiple:
+ codeunit = MultipleCodeUnit.MultipleCodeUnit(module, out)
+ else:
+ codeunit = SingleCodeUnit.SingleCodeUnit(module, out)
+ # stop referencing the exporters here
+ exports = exporters.exporters
+ exporters.exporters = None
+ exported_names = dict([(x.Name(), None) for x in exports])
+
+ # order the exports
+ order = {}
+ for export in exports:
+ if export.interface_file in order:
+ order[export.interface_file].append(export)
+ else:
+ order[export.interface_file] = [export]
+ exports = []
+ interfaces_order = OrderInterfaces(interfaces)
+ for interface in interfaces_order:
+ exports.extend(order[interface])
+ del order
+ del interfaces_order
+
+ # now generate the code in the correct order
+ #print exported_names
+ tails = JoinTails(exports)
+ for i in xrange(len(exports)):
+ export = exports[i]
+ interface = export.interface_file
+ header = export.Header()
+ if header:
+ tail = tails[(interface, header)]
+ declarations, parsed_header = parser.Parse(header, interface, tail)
+ else:
+ declarations = []
+ parsed_header = None
+ ExpandTypedefs(declarations, exported_names)
+ export.SetDeclarations(declarations)
+ export.SetParsedHeader(parsed_header)
+ if multiple:
+ codeunit.SetCurrent(export.interface_file, export.Name())
+ export.GenerateCode(codeunit, exported_names)
+ # force collect of cyclic references
+ exports[i] = None
+ del declarations
+ del export
+ gc.collect()
+ # finally save the code unit
+ codeunit.Save()
+ if not multiple:
+ print 'Module %s generated' % module
+ return 0
+
+
+def ExpandTypedefs(decls, exported_names):
+ '''Check if the names in exported_names are a typedef, and add the real class
+ name in the dict.
+ '''
+ for name in exported_names.keys():
+ for decl in decls:
+ if isinstance(decl, declarations.Typedef):
+ exported_names[decl.type.FullName()] = None
+
+def UsePsyco():
+ 'Tries to use psyco if possible'
+ try:
+ import psyco
+ psyco.profile()
+ except: pass
+
+
+def main():
+ start = time.clock()
+ UsePsyco()
+ status = Begin()
+ print '%0.2f seconds' % (time.clock()-start)
+ sys.exit(status)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/libs/python/pyste/src/Pyste/settings.py b/libs/python/pyste/src/Pyste/settings.py
new file mode 100644
index 000000000..ba613b234
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/settings.py
@@ -0,0 +1,21 @@
+# 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)
+
+
+#==============================================================================
+# Global information
+#==============================================================================
+
+DEBUG = False
+USING_BOOST_NS = True
+
+class namespaces:
+ boost = 'boost::'
+ pyste = ''
+ python = '' # default is to not use boost::python namespace explicitly, so
+ # use the "using namespace" statement instead
+
+import sys
+msvc = sys.platform == 'win32'
diff --git a/libs/python/pyste/src/Pyste/utils.py b/libs/python/pyste/src/Pyste/utils.py
new file mode 100644
index 000000000..a8843e3f6
--- /dev/null
+++ b/libs/python/pyste/src/Pyste/utils.py
@@ -0,0 +1,78 @@
+# 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 __future__ import generators
+import string
+import sys
+
+#==============================================================================
+# enumerate
+#==============================================================================
+def enumerate(seq):
+ i = 0
+ for x in seq:
+ yield i, x
+ i += 1
+
+
+#==============================================================================
+# makeid
+#==============================================================================
+_valid_chars = string.ascii_letters + string.digits + '_'
+_valid_chars = dict(zip(_valid_chars, _valid_chars))
+
+def makeid(name):
+ 'Returns the name as a valid identifier'
+ if type(name) != str:
+ print type(name), name
+ newname = []
+ for char in name:
+ if char not in _valid_chars:
+ char = '_'
+ newname.append(char)
+ newname = ''.join(newname)
+ # avoid duplications of '_' chars
+ names = [x for x in newname.split('_') if x]
+ return '_'.join(names)
+
+
+#==============================================================================
+# remove_duplicated_lines
+#==============================================================================
+def remove_duplicated_lines(text):
+ includes = text.splitlines()
+ d = dict([(include, 0) for include in includes])
+ includes = d.keys()
+ includes.sort()
+ return '\n'.join(includes)
+
+
+#==============================================================================
+# left_equals
+#==============================================================================
+def left_equals(s):
+ s = '// %s ' % s
+ return s + ('='*(80-len(s))) + '\n'
+
+
+#==============================================================================
+# post_mortem
+#==============================================================================
+def post_mortem():
+
+ def info(type, value, tb):
+ if hasattr(sys, 'ps1') or not sys.stderr.isatty():
+ # we are in interactive mode or we don't have a tty-like
+ # device, so we call the default hook
+ sys.__excepthook__(type, value, tb)
+ else:
+ import traceback, pdb
+ # we are NOT in interactive mode, print the exception...
+ traceback.print_exception(type, value, tb)
+ print
+ # ...then start the debugger in post-mortem mode.
+ pdb.pm()
+
+ sys.excepthook = info
diff --git a/libs/python/pyste/tests/GCCXMLParserUT.py b/libs/python/pyste/tests/GCCXMLParserUT.py
new file mode 100644
index 000000000..7175c9c68
--- /dev/null
+++ b/libs/python/pyste/tests/GCCXMLParserUT.py
@@ -0,0 +1,341 @@
+# 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)
+
+import sys
+sys.path.append('../src')
+import unittest
+import tempfile
+import os.path
+from Pyste import GCCXMLParser
+from Pyste.declarations import *
+
+
+class Tester(unittest.TestCase):
+
+ def TestConstructor(self, class_, method, visib):
+ self.assert_(isinstance(method, Constructor))
+ self.assertEqual(method.FullName(), class_.FullName() + '::' + method.name)
+ self.assertEqual(method.result, None)
+ self.assertEqual(method.visibility, visib)
+ self.assert_(not method.virtual)
+ self.assert_(not method.abstract)
+ self.assert_(not method.static)
+
+ def TestDefaultConstructor(self, class_, method, visib):
+ self.TestConstructor(class_, method, visib)
+ self.assert_(method.IsDefault())
+
+ def TestCopyConstructor(self, class_, method, visib):
+ self.TestConstructor(class_, method, visib)
+ self.assertEqual(len(method.parameters), 1)
+ param = method.parameters[0]
+ self.TestType(
+ param,
+ ReferenceType,
+ class_.FullName(),
+ 'const %s&' % class_.FullName(),
+ True)
+ self.assert_(method.IsCopy())
+
+
+ def TestType(self, type_, classtype_, name, fullname, const):
+ self.assert_(isinstance(type_, classtype_))
+ self.assertEqual(type_.name, name)
+ self.assertEqual(type_.namespace, None)
+ self.assertEqual(type_.FullName(), fullname)
+ self.assertEqual(type_.const, const)
+
+
+class ClassBaseTest(Tester):
+
+ def setUp(self):
+ self.base = GetDecl('Base')
+
+ def testClass(self):
+ 'test the properties of the class Base'
+ self.assert_(isinstance(self.base, Class))
+ self.assert_(self.base.abstract)
+
+
+ def testFoo(self):
+ 'test function foo in class Base'
+ foo = GetMember(self.base, 'foo')
+ self.assert_(isinstance(foo, Method))
+ self.assertEqual(foo.visibility, Scope.public)
+ self.assert_(foo.virtual)
+ self.assert_(foo.abstract)
+ self.failIf(foo.static)
+ self.assertEqual(foo.class_, 'test::Base')
+ self.failIf(foo.const)
+ self.assertEqual(foo.FullName(), 'test::Base::foo')
+ self.assertEqual(foo.result.name, 'void')
+ self.assertEqual(len(foo.parameters), 1)
+ param = foo.parameters[0]
+ self.TestType(param, FundamentalType, 'int', 'int', False)
+ self.assertEqual(foo.namespace, None)
+ self.assertEqual(
+ foo.PointerDeclaration(1), '(void (test::Base::*)(int) )&test::Base::foo')
+
+ def testX(self):
+ 'test the member x in class Base'
+ x = GetMember(self.base, 'x')
+ self.assertEqual(x.class_, 'test::Base')
+ self.assertEqual(x.FullName(), 'test::Base::x')
+ self.assertEqual(x.namespace, None)
+ self.assertEqual(x.visibility, Scope.private)
+ self.TestType(x.type, FundamentalType, 'int', 'int', False)
+ self.assertEqual(x.static, False)
+
+ def testConstructors(self):
+ 'test constructors in class Base'
+ constructors = GetMembers(self.base, 'Base')
+ for cons in constructors:
+ if len(cons.parameters) == 0:
+ self.TestDefaultConstructor(self.base, cons, Scope.public)
+ elif len(cons.parameters) == 1: # copy constructor
+ self.TestCopyConstructor(self.base, cons, Scope.public)
+ elif len(cons.parameters) == 2: # other constructor
+ intp, floatp = cons.parameters
+ self.TestType(intp, FundamentalType, 'int', 'int', False)
+ self.TestType(floatp, FundamentalType, 'float', 'float', False)
+
+ def testSimple(self):
+ 'test function simple in class Base'
+ simple = GetMember(self.base, 'simple')
+ self.assert_(isinstance(simple, Method))
+ self.assertEqual(simple.visibility, Scope.protected)
+ self.assertEqual(simple.FullName(), 'test::Base::simple')
+ self.assertEqual(len(simple.parameters), 1)
+ param = simple.parameters[0]
+ self.TestType(param, ReferenceType, 'std::string', 'const std::string&', True)
+ self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
+ self.assertEqual(
+ simple.PointerDeclaration(1),
+ '(bool (test::Base::*)(const std::string&) )&test::Base::simple')
+
+
+ def testZ(self):
+ z = GetMember(self.base, 'z')
+ self.assert_(isinstance(z, Variable))
+ self.assertEqual(z.visibility, Scope.public)
+ self.assertEqual(z.FullName(), 'test::Base::z')
+ self.assertEqual(z.type.name, 'int')
+ self.assertEqual(z.type.const, False)
+ self.assert_(z.static)
+
+
+class ClassTemplateTest(Tester):
+
+ def setUp(self):
+ self.template = GetDecl('Template<int>')
+
+ def testClass(self):
+ 'test the properties of the Template<int> class'
+ self.assert_(isinstance(self.template, Class))
+ self.assert_(not self.template.abstract)
+ self.assertEqual(self.template.FullName(), 'Template<int>')
+ self.assertEqual(self.template.namespace, '')
+ self.assertEqual(self.template.name, 'Template<int>')
+
+ def testConstructors(self):
+ 'test the automatic constructors of the class Template<int>'
+ constructors = GetMembers(self.template, 'Template')
+ for cons in constructors:
+ if len(cons.parameters) == 0:
+ self.TestDefaultConstructor(self.template, cons, Scope.public)
+ elif len(cons.parameters) == 1:
+ self.TestCopyConstructor(self.template, cons, Scope.public)
+
+
+ def testValue(self):
+ 'test the class variable value'
+ value = GetMember(self.template, 'value')
+ self.assert_(isinstance(value, ClassVariable))
+ self.assert_(value.name, 'value')
+ self.TestType(value.type, FundamentalType, 'int', 'int', False)
+ self.assert_(not value.static)
+ self.assertEqual(value.visibility, Scope.public)
+ self.assertEqual(value.class_, 'Template<int>')
+ self.assertEqual(value.FullName(), 'Template<int>::value')
+
+ def testBase(self):
+ 'test the superclasses of Template<int>'
+ bases = self.template.bases
+ self.assertEqual(len(bases), 1)
+ base = bases[0]
+ self.assert_(isinstance(base, Base))
+ self.assertEqual(base.name, 'test::Base')
+ self.assertEqual(base.visibility, Scope.protected)
+
+
+
+class FreeFuncTest(Tester):
+
+ def setUp(self):
+ self.func = GetDecl('FreeFunc')
+
+ def testFunc(self):
+ 'test attributes of FreeFunc'
+ self.assert_(isinstance(self.func, Function))
+ self.assertEqual(self.func.name, 'FreeFunc')
+ self.assertEqual(self.func.FullName(), 'test::FreeFunc')
+ self.assertEqual(self.func.namespace, 'test')
+ self.assertEqual(
+ self.func.PointerDeclaration(1),
+ '(const test::Base& (*)(const std::string&, int))&test::FreeFunc')
+
+
+ def testResult(self):
+ 'test the return value of FreeFunc'
+ res = self.func.result
+ self.TestType(res, ReferenceType, 'test::Base', 'const test::Base&', True)
+
+ def testParameters(self):
+ 'test the parameters of FreeFunc'
+ self.assertEqual(len(self.func.parameters), 2)
+ strp, intp = self.func.parameters
+ self.TestType(strp, ReferenceType, 'std::string', 'const std::string&', True)
+ self.assertEqual(strp.default, None)
+ self.TestType(intp, FundamentalType, 'int', 'int', False)
+ self.assertEqual(intp.default, '10')
+
+
+
+class testFunctionPointers(Tester):
+
+ def testMethodPointer(self):
+ 'test declaration of a pointer-to-method'
+ meth = GetDecl('MethodTester')
+ param = meth.parameters[0]
+ fullname = 'void (test::Base::*)(int)'
+ self.TestType(param, PointerType, fullname, fullname, False)
+
+ def testFunctionPointer(self):
+ 'test declaration of a pointer-to-function'
+ func = GetDecl('FunctionTester')
+ param = func.parameters[0]
+ fullname = 'void (*)(int)'
+ self.TestType(param, PointerType, fullname, fullname, False)
+
+
+
+# =============================================================================
+# Support routines
+# =============================================================================
+
+cppcode = '''
+namespace std {
+ class string;
+}
+namespace test {
+class Base
+{
+public:
+ Base();
+ Base(const Base&);
+ Base(int, float);
+
+ virtual void foo(int = 0.0) = 0;
+ static int z;
+protected:
+ bool simple(const std::string&);
+private:
+ int x;
+};
+
+void MethodTester( void (Base::*)(int) );
+void FunctionTester( void (*)(int) );
+
+
+const Base & FreeFunc(const std::string&, int=10);
+
+}
+
+template <class T>
+struct Template: protected test::Base
+{
+ T value;
+ virtual void foo(int);
+};
+
+Template<int> __aTemplateInt;
+'''
+
+def GetXMLFile():
+ '''Generates an gccxml file using the code from the global cppcode.
+ Returns the xml's filename.'''
+ # write the code to a header file
+ tmpfile = tempfile.mktemp() + '.h'
+ f = file(tmpfile, 'w')
+ f.write(cppcode)
+ f.close()
+ # run gccxml
+ outfile = tmpfile + '.xml'
+ if os.system('gccxml "%s" "-fxml=%s"' % (tmpfile, outfile)) != 0:
+ raise RuntimeError, 'Error executing GCCXML.'
+ # read the output file into the xmlcode
+ f = file(outfile)
+ xmlcode = f.read()
+ #print xmlcode
+ f.close()
+ # remove the header
+ os.remove(tmpfile)
+ return outfile
+
+
+
+def GetDeclarations():
+ 'Uses the GCCXMLParser module to get the declarations.'
+ xmlfile = GetXMLFile()
+ declarations = GCCXMLParser.ParseDeclarations(xmlfile)
+ os.remove(xmlfile)
+ return declarations
+
+# the declarations to be analysed
+declarations = GetDeclarations()
+
+
+def GetDecl(name):
+ 'returns one of the top declarations given its name'
+ for decl in declarations:
+ if decl.name == name:
+ return decl
+ else:
+ raise RuntimeError, 'Declaration not found: %s' % name
+
+
+def GetMember(class_, name):
+ 'gets the member of the given class by its name'
+
+ res = None
+ multipleFound = False
+ for member in class_:
+ if member.name == name:
+ if res is not None:
+ multipleFound = True
+ break
+ res = member
+ if res is None or multipleFound:
+ raise RuntimeError, \
+ 'No member or more than one member found in class %s: %s' \
+ % (class_.name, name)
+ return res
+
+
+def GetMembers(class_, name):
+ 'gets the members of the given class by its name'
+ res = []
+ for member in class_:
+ if member.name == name:
+ res.append(member)
+ if len(res) in (0, 1):
+ raise RuntimeError, \
+ 'GetMembers: 0 or 1 members found in class %s: %s' \
+ % (class_.name, name)
+ return res
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/SmartFileUT.py b/libs/python/pyste/tests/SmartFileUT.py
new file mode 100644
index 000000000..9e4e99883
--- /dev/null
+++ b/libs/python/pyste/tests/SmartFileUT.py
@@ -0,0 +1,84 @@
+# 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)
+import sys
+sys.path.append('../src')
+from SmartFile import *
+import unittest
+import tempfile
+import os
+import time
+
+
+class SmartFileTest(unittest.TestCase):
+
+ FILENAME = tempfile.mktemp()
+
+ def setUp(self):
+ self._Clean()
+
+ def tearDown(self):
+ self._Clean()
+
+ def _Clean(self):
+ try:
+ os.remove(self.FILENAME)
+ except OSError: pass
+
+
+ def testNonExistant(self):
+ "Must override the file, as there's no file in the disk yet"
+ self.assert_(not os.path.isfile(self.FILENAME))
+ f = SmartFile(self.FILENAME, 'w')
+ f.write('Testing 123\nTesting again.')
+ f.close()
+ self.assert_(os.path.isfile(self.FILENAME))
+
+
+ def testOverride(self):
+ "Must override the file, because the contents are different"
+ contents = 'Contents!\nContents!'
+ # create the file normally first
+ f = file(self.FILENAME, 'w')
+ f.write(contents)
+ f.close()
+ file_time = os.path.getmtime(self.FILENAME)
+ self.assert_(os.path.isfile(self.FILENAME))
+ time.sleep(2)
+ f = SmartFile(self.FILENAME, 'w')
+ f.write(contents + '_')
+ f.close()
+ new_file_time = os.path.getmtime(self.FILENAME)
+ self.assert_(new_file_time != file_time)
+
+
+ def testNoOverride(self):
+ "Must not override the file, because the contents are the same"
+ contents = 'Contents!\nContents!'
+ # create the file normally first
+ f = file(self.FILENAME, 'w')
+ f.write(contents)
+ f.close()
+ file_time = os.path.getmtime(self.FILENAME)
+ self.assert_(os.path.isfile(self.FILENAME))
+ time.sleep(2)
+ f = SmartFile(self.FILENAME, 'w')
+ f.write(contents)
+ f.close()
+ new_file_time = os.path.getmtime(self.FILENAME)
+ self.assert_(new_file_time == file_time)
+
+
+ def testAutoClose(self):
+ "Must be closed when garbage-collected"
+ def foo():
+ f = SmartFile(self.FILENAME)
+ f.write('testing')
+ self.assert_(not os.path.isfile(self.FILENAME))
+ foo()
+ self.assert_(os.path.isfile(self.FILENAME))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/abstract_test.h b/libs/python/pyste/tests/abstract_test.h
new file mode 100644
index 000000000..e0fba2b24
--- /dev/null
+++ b/libs/python/pyste/tests/abstract_test.h
@@ -0,0 +1,22 @@
+/* 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)
+ */
+#include <vector>
+#include <string>
+
+namespace abstract {
+
+struct A {
+ virtual ~A() {}
+ virtual std::string f()=0;
+};
+
+struct B: A {
+ std::string f() { return "B::f"; }
+};
+
+std::string call(A* a) { return a->f(); }
+
+}
diff --git a/libs/python/pyste/tests/abstract_test.pyste b/libs/python/pyste/tests/abstract_test.pyste
new file mode 100644
index 000000000..c65bb3ad6
--- /dev/null
+++ b/libs/python/pyste/tests/abstract_test.pyste
@@ -0,0 +1,3 @@
+Class('abstract::A', 'abstract_test.h')
+Class('abstract::B', 'abstract_test.h')
+Function('abstract::call', 'abstract_test.h')
diff --git a/libs/python/pyste/tests/abstract_testUT.py b/libs/python/pyste/tests/abstract_testUT.py
new file mode 100644
index 000000000..4dc61a262
--- /dev/null
+++ b/libs/python/pyste/tests/abstract_testUT.py
@@ -0,0 +1,26 @@
+# 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)
+import unittest
+from _abstract_test import *
+
+class AbstractTest(unittest.TestCase):
+
+ def testIt(self):
+ class C(A):
+ def f(self):
+ return 'C::f'
+
+ a = A()
+ b = B()
+ c = C()
+ self.assertRaises(RuntimeError, a.f)
+ self.assertEqual(b.f(), 'B::f')
+ self.assertEqual(call(b), 'B::f')
+ self.assertEqual(c.f(), 'C::f')
+ self.assertEqual(call(c), 'C::f')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/add_test.h b/libs/python/pyste/tests/add_test.h
new file mode 100644
index 000000000..447e8814c
--- /dev/null
+++ b/libs/python/pyste/tests/add_test.h
@@ -0,0 +1,18 @@
+/* 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)
+ */
+namespace add_test {
+
+struct C
+{
+ int x;
+};
+
+const int get_x(C& c)
+{
+ return c.x;
+}
+
+}
diff --git a/libs/python/pyste/tests/add_test.pyste b/libs/python/pyste/tests/add_test.pyste
new file mode 100644
index 000000000..cc7faa9ed
--- /dev/null
+++ b/libs/python/pyste/tests/add_test.pyste
@@ -0,0 +1,2 @@
+C = Class('add_test::C', 'add_test.h')
+add_method(C, 'add_test::get_x')
diff --git a/libs/python/pyste/tests/add_testUT.py b/libs/python/pyste/tests/add_testUT.py
new file mode 100644
index 000000000..16f57a320
--- /dev/null
+++ b/libs/python/pyste/tests/add_testUT.py
@@ -0,0 +1,16 @@
+# 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)
+import unittest
+from _add_test import *
+
+class AddMethodTest(unittest.TestCase):
+
+ def testIt(self):
+ c = C()
+ c.x = 10
+ self.assertEqual(c.get_x(), 10)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/basic.cpp b/libs/python/pyste/tests/basic.cpp
new file mode 100644
index 000000000..d07b6da62
--- /dev/null
+++ b/libs/python/pyste/tests/basic.cpp
@@ -0,0 +1,13 @@
+/* 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)
+ */
+#include "basic.h"
+
+namespace basic {
+
+ int C::static_value = 3;
+ const int C::const_static_value = 100;
+
+}
diff --git a/libs/python/pyste/tests/basic.h b/libs/python/pyste/tests/basic.h
new file mode 100644
index 000000000..690fed2d3
--- /dev/null
+++ b/libs/python/pyste/tests/basic.h
@@ -0,0 +1,69 @@
+/* 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)
+ */
+#ifndef BASIC_H
+#define BASIC_H
+
+
+#include <string>
+
+namespace basic {
+
+struct C
+{
+ // test virtuallity
+ C(): value(1), const_value(0) {}
+ virtual int f(int x = 10)
+ {
+ return x*2;
+ }
+
+ int foo(int x=1){
+ return x+1;
+ }
+
+ const std::string& get_name() { return name; }
+ void set_name(const std::string& name) { this->name = name; }
+private:
+ std::string name;
+
+public:
+ // test data members
+ static int static_value;
+ static const int const_static_value;
+
+ int value;
+ const int const_value;
+
+ // test static functions
+ static int mul(int x, int y) { return x*y; }
+ static double mul(double x, double y) { return x*y; }
+
+ static int square(int x=2) { return x*x; }
+};
+
+inline int call_f(C& c)
+{
+ return c.f();
+}
+
+inline int call_f(C& c, int x)
+{
+ return c.f(x);
+}
+
+inline int get_static()
+{
+ return C::static_value;
+}
+
+inline int get_value(C& c)
+{
+ return c.value;
+}
+
+}
+
+#endif
diff --git a/libs/python/pyste/tests/basic.pyste b/libs/python/pyste/tests/basic.pyste
new file mode 100644
index 000000000..4fe0b5b31
--- /dev/null
+++ b/libs/python/pyste/tests/basic.pyste
@@ -0,0 +1,5 @@
+Class('basic::C', 'basic.h')
+Function('basic::call_f', 'basic.h')
+Function('basic::get_static', 'basic.h')
+Function('basic::get_value', 'basic.h')
+
diff --git a/libs/python/pyste/tests/basicUT.py b/libs/python/pyste/tests/basicUT.py
new file mode 100644
index 000000000..9a18bcbf3
--- /dev/null
+++ b/libs/python/pyste/tests/basicUT.py
@@ -0,0 +1,73 @@
+# 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)
+import unittest
+from _basic import *
+
+class BasicExampleTest(unittest.TestCase):
+
+ def testIt(self):
+
+ # test virtual functions
+ class D(C):
+ def f(self, x=10):
+ return x+1
+
+ d = D()
+ c = C()
+
+ self.assertEqual(c.f(), 20)
+ self.assertEqual(c.f(3), 6)
+ self.assertEqual(d.f(), 11)
+ self.assertEqual(d.f(3), 4)
+ self.assertEqual(call_f(c), 20)
+ self.assertEqual(call_f(c, 4), 8)
+ self.assertEqual(call_f(d), 11)
+ self.assertEqual(call_f(d, 3), 4)
+
+ # test data members
+ def testValue(value):
+ self.assertEqual(c.value, value)
+ self.assertEqual(d.value, value)
+ self.assertEqual(get_value(c), value)
+ self.assertEqual(get_value(d), value)
+ testValue(1)
+ c.value = 30
+ d.value = 30
+ testValue(30)
+ self.assertEqual(c.const_value, 0)
+ self.assertEqual(d.const_value, 0)
+ def set_const_value():
+ c.const_value = 12
+ self.assertRaises(AttributeError, set_const_value)
+
+ # test static data-members
+ def testStatic(value):
+ self.assertEqual(C.static_value, value)
+ self.assertEqual(c.static_value, value)
+ self.assertEqual(D.static_value, value)
+ self.assertEqual(d.static_value, value)
+ self.assertEqual(get_static(), value)
+ testStatic(3)
+ C.static_value = 10
+ testStatic(10)
+ self.assertEqual(C.const_static_value, 100)
+ def set_const_static():
+ C.const_static_value = 1
+ self.assertRaises(AttributeError, set_const_static)
+
+ # test static function
+ def test_mul(result, *args):
+ self.assertEqual(C.mul(*args), result)
+ self.assertEqual(c.mul(*args), result)
+ test_mul(16, 8, 2)
+ test_mul(6.0, 2.0, 3.0)
+ self.assertEqual(C.square(), 4)
+ self.assertEqual(c.square(), 4)
+ self.assertEqual(C.square(3), 9)
+ self.assertEqual(c.square(3), 9)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/code_test.h b/libs/python/pyste/tests/code_test.h
new file mode 100644
index 000000000..0a31205a3
--- /dev/null
+++ b/libs/python/pyste/tests/code_test.h
@@ -0,0 +1,8 @@
+/* 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)
+ */
+struct A {
+ int x;
+};
diff --git a/libs/python/pyste/tests/code_test.pyste b/libs/python/pyste/tests/code_test.pyste
new file mode 100644
index 000000000..467996fdb
--- /dev/null
+++ b/libs/python/pyste/tests/code_test.pyste
@@ -0,0 +1,9 @@
+Class('A', 'code_test.h')
+Include('string')
+declaration_code('''
+int get(A& a) { return a.x; }
+
+std::string foo() { return "Hello!"; }
+''')
+module_code(' def("get", &get);\n')
+module_code(' def("foo", &foo);\n')
diff --git a/libs/python/pyste/tests/code_testUT.py b/libs/python/pyste/tests/code_testUT.py
new file mode 100644
index 000000000..1059570aa
--- /dev/null
+++ b/libs/python/pyste/tests/code_testUT.py
@@ -0,0 +1,18 @@
+# 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)
+import unittest
+from _code_test import *
+
+class CodeTest(unittest.TestCase):
+
+ def testIt(self):
+ a = A()
+ a.x = 12
+ self.assertEqual(get(a), 12)
+ self.assertEqual(foo(), "Hello!")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/enums.h b/libs/python/pyste/tests/enums.h
new file mode 100644
index 000000000..afe33ca48
--- /dev/null
+++ b/libs/python/pyste/tests/enums.h
@@ -0,0 +1,34 @@
+/* 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)
+ */
+#ifndef ENUMS_H
+#define ENUMS_H
+
+namespace enums {
+
+enum color { red, blue };
+
+struct X
+{
+ enum choices
+ {
+ good = 1,
+ bad = 2
+ };
+
+ int set(choices c)
+ {
+ return (int)c;
+ }
+};
+
+enum {
+ x = 0,
+ y = 1
+};
+
+}
+
+#endif
diff --git a/libs/python/pyste/tests/enums.pyste b/libs/python/pyste/tests/enums.pyste
new file mode 100644
index 000000000..c18a1244f
--- /dev/null
+++ b/libs/python/pyste/tests/enums.pyste
@@ -0,0 +1,8 @@
+h = AllFromHeader('enums.h')
+rename(h.color.red, 'Red')
+rename(h.color.blue, 'Blue')
+export_values(h.color)
+rename(h.X.choices.bad, 'Bad')
+rename(h.X.choices.good, 'Good')
+rename(h.X.choices, 'Choices')
+
diff --git a/libs/python/pyste/tests/enumsUT.py b/libs/python/pyste/tests/enumsUT.py
new file mode 100644
index 000000000..7c7720dcb
--- /dev/null
+++ b/libs/python/pyste/tests/enumsUT.py
@@ -0,0 +1,24 @@
+# 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)
+import unittest
+from _enums import *
+
+class EnumsTest(unittest.TestCase):
+
+ def testIt(self):
+ self.assertEqual(int(Red), 0)
+ self.assertEqual(int(Blue), 1)
+
+ self.assertEqual(int(X.Choices.Good), 1)
+ self.assertEqual(int(X.Choices.Bad), 2)
+ a = X()
+ self.assertEqual(a.set(a.Choices.Good), 1)
+ self.assertEqual(a.set(a.Choices.Bad), 2)
+ self.assertEqual(x, 0)
+ self.assertEqual(y, 1)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/header_test.h b/libs/python/pyste/tests/header_test.h
new file mode 100644
index 000000000..030d0d26c
--- /dev/null
+++ b/libs/python/pyste/tests/header_test.h
@@ -0,0 +1,43 @@
+/* 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)
+ */
+#ifndef HEADER_TEST_H
+#define HEADER_TEST_H
+
+#include <map>
+#include <string>
+
+namespace header_test {
+
+enum choice { red, blue };
+
+inline std::string choice_str(choice c)
+{
+ std::map<choice, std::string> choice_map;
+ choice_map[red] = "red";
+ choice_map[blue] = "blue";
+ return choice_map[c];
+}
+
+struct C
+{
+ choice c;
+
+ std::string get()
+ {
+ return choice_str(c);
+ }
+};
+
+// test the exclusion of the following
+
+struct ForwardDeclared; // should be excluded automatically
+struct A {};
+void foo();
+enum bar { value };
+
+}
+
+#endif
diff --git a/libs/python/pyste/tests/header_test.pyste b/libs/python/pyste/tests/header_test.pyste
new file mode 100644
index 000000000..3bd55501c
--- /dev/null
+++ b/libs/python/pyste/tests/header_test.pyste
@@ -0,0 +1,4 @@
+h = AllFromHeader('header_test.h')
+exclude(h.A)
+exclude(h.foo)
+exclude(h.bar)
diff --git a/libs/python/pyste/tests/header_testUT.py b/libs/python/pyste/tests/header_testUT.py
new file mode 100644
index 000000000..aa0d4a16f
--- /dev/null
+++ b/libs/python/pyste/tests/header_testUT.py
@@ -0,0 +1,27 @@
+# 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)
+import unittest
+from _header_test import *
+
+class HeaderTest(unittest.TestCase):
+
+ def testIt(self):
+ self.assertEqual(choice.red, 0)
+ self.assertEqual(choice.blue, 1)
+ self.assertEqual(choice_str(choice.blue), 'blue')
+ self.assertEqual(choice_str(choice.red), 'red')
+ c = C()
+ c.c = choice.blue
+ self.assertEqual(c.get(), 'blue')
+ c.c = choice.red
+ self.assertEqual(c.get(), 'red')
+ # the following classes/functions should not have being exported
+ self.assertRaises(NameError, lambda: A())
+ self.assertRaises(NameError, lambda: foo())
+ self.assertRaises(NameError, lambda: bar.value)
+ self.assertRaises(NameError, lambda: ForwardDeclared())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/infosUT.py b/libs/python/pyste/tests/infosUT.py
new file mode 100644
index 000000000..93769f34e
--- /dev/null
+++ b/libs/python/pyste/tests/infosUT.py
@@ -0,0 +1,55 @@
+# 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)
+import sys
+from Pyste.infos import *
+from Pyste.policies import *
+from Pyste.exporterutils import *
+import unittest
+
+#================================================================================
+# InfosTest
+#================================================================================
+class InfosTest(unittest.TestCase):
+
+ def testFunctionInfo(self):
+ info = FunctionInfo('test::foo', 'foo.h')
+ rename(info, 'hello')
+ set_policy(info, return_internal_reference())
+ set_wrapper(info, FunctionWrapper('foo_wrapper'))
+
+ info = InfoWrapper(info)
+
+ self.assertEqual(info.rename, 'hello')
+ self.assertEqual(info.policy.Code(), 'return_internal_reference< 1 >')
+ self.assertEqual(info.wrapper.name, 'foo_wrapper')
+
+
+ def testClassInfo(self):
+ info = ClassInfo('test::IFoo', 'foo.h')
+ rename(info.name, 'Name')
+ rename(info.exclude, 'Exclude')
+ rename(info, 'Foo')
+ rename(info.Bar, 'bar')
+ set_policy(info.Baz, return_internal_reference())
+ rename(info.operator['>>'], 'from_string')
+ exclude(info.Bar)
+ set_wrapper(info.Baz, FunctionWrapper('baz_wrapper'))
+
+ info = InfoWrapper(info)
+
+ self.assertEqual(info.rename, 'Foo')
+ self.assertEqual(info['Bar'].rename, 'bar')
+ self.assertEqual(info['name'].rename, 'Name')
+ self.assertEqual(info['exclude'].rename, 'Exclude')
+ self.assertEqual(info['Bar'].exclude, True)
+ self.assertEqual(info['Baz'].policy.Code(), 'return_internal_reference< 1 >')
+ self.assertEqual(info['Baz'].wrapper.name, 'baz_wrapper')
+ self.assertEqual(info['operator']['>>'].rename, 'from_string')
+
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/inherit.cpp b/libs/python/pyste/tests/inherit.cpp
new file mode 100644
index 000000000..a75e83891
--- /dev/null
+++ b/libs/python/pyste/tests/inherit.cpp
@@ -0,0 +1,8 @@
+/* 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)
+ */
+#include "inherit.h"
+
+int inherit::C::s = 1;
diff --git a/libs/python/pyste/tests/inherit.h b/libs/python/pyste/tests/inherit.h
new file mode 100644
index 000000000..8f903f4fd
--- /dev/null
+++ b/libs/python/pyste/tests/inherit.h
@@ -0,0 +1,43 @@
+/* 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)
+ */
+namespace inherit {
+
+template<typename T>
+class A
+{
+public:
+ void set(T v) { mData = v; }
+
+ T get() const { return mData; }
+
+private:
+ T mData;
+};
+
+
+class B : public A<int>
+{
+public:
+ int go() { return get(); }
+};
+
+struct C : B
+{
+ enum ab { a = 1, b = 2 };
+ int f1() { return 1; }
+ int x;
+ static int s;
+};
+
+struct D : C
+{
+ int f2() { return 2; }
+ int y;
+};
+
+struct X {};
+struct E: X, D {};
+}
diff --git a/libs/python/pyste/tests/inherit.pyste b/libs/python/pyste/tests/inherit.pyste
new file mode 100644
index 000000000..0dc029989
--- /dev/null
+++ b/libs/python/pyste/tests/inherit.pyste
@@ -0,0 +1,8 @@
+A = Template('inherit::A', 'inherit.h')
+A_int = A('int', 'A_int')
+
+Class('inherit::B', 'inherit.h')
+Class('inherit::D', 'inherit.h')
+E = Class('inherit::E', 'inherit.h')
+exclude(E.s)
+exclude(E.ab)
diff --git a/libs/python/pyste/tests/inherit2.h b/libs/python/pyste/tests/inherit2.h
new file mode 100644
index 000000000..af9387bd0
--- /dev/null
+++ b/libs/python/pyste/tests/inherit2.h
@@ -0,0 +1,35 @@
+/* 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)
+ */
+namespace inherit2 {
+
+struct A
+{
+ int x;
+ int getx() { return x; }
+ int foo() { return 0; }
+ int foo(int x) { return x; }
+};
+
+struct B : A
+{
+ int y;
+ int gety() { return y; }
+ int foo() { return 1; }
+};
+
+struct C : B
+{
+ int z;
+ int getz() { return z; }
+};
+
+struct D : C
+{
+ int w;
+ int getw() { return w; }
+};
+
+}
diff --git a/libs/python/pyste/tests/inherit2.pyste b/libs/python/pyste/tests/inherit2.pyste
new file mode 100644
index 000000000..380821398
--- /dev/null
+++ b/libs/python/pyste/tests/inherit2.pyste
@@ -0,0 +1,2 @@
+Class('inherit2::B', 'inherit2.h')
+Class('inherit2::D', 'inherit2.h')
diff --git a/libs/python/pyste/tests/inherit2UT.py b/libs/python/pyste/tests/inherit2UT.py
new file mode 100644
index 000000000..85afce617
--- /dev/null
+++ b/libs/python/pyste/tests/inherit2UT.py
@@ -0,0 +1,31 @@
+# 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)
+import unittest
+from _inherit2 import *
+
+class InheritExampleTest(unittest.TestCase):
+
+ def testIt(self):
+ b = B()
+ d = D()
+
+ self.assert_(issubclass(D, B))
+ b.x, b.y = 10, 5
+ self.assertEqual(b.getx(), 10)
+ self.assertEqual(b.gety(), 5)
+ d.x, d.y, d.z, d.w = 20, 15, 10, 5
+ self.assertEqual(d.getx(), 20)
+ self.assertEqual(d.gety(), 15)
+ self.assertEqual(d.getz(), 10)
+ self.assertEqual(d.getw(), 5)
+ self.assertEqual(b.foo(), 1)
+ self.assertEqual(b.foo(3), 3)
+
+ def wrong():
+ return b.getw()
+ self.assertRaises(AttributeError, wrong)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/inherit3.h b/libs/python/pyste/tests/inherit3.h
new file mode 100644
index 000000000..1945fb514
--- /dev/null
+++ b/libs/python/pyste/tests/inherit3.h
@@ -0,0 +1,46 @@
+/* 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)
+ */
+
+namespace inherit3 {
+
+struct A
+{
+ A() { x = 0; }
+ struct X { int y; };
+ int x;
+ virtual int foo() { return 0; }
+ virtual int foo(int x) { return x; }
+ A operator+(A o) const
+ {
+ A r;
+ r.x = o.x + x;
+ return r;
+ }
+ enum E { i, j };
+
+};
+
+struct B: A
+{
+ B() { x = 0; }
+ struct X { int y; };
+ int x;
+ int foo() { return 1; }
+ A operator+(A o) const
+ {
+ A r;
+ r.x = o.x + x;
+ return r;
+ }
+ enum E { i, j };
+
+};
+
+struct C: A
+{
+};
+
+}
diff --git a/libs/python/pyste/tests/inherit3.pyste b/libs/python/pyste/tests/inherit3.pyste
new file mode 100644
index 000000000..f95c06054
--- /dev/null
+++ b/libs/python/pyste/tests/inherit3.pyste
@@ -0,0 +1,2 @@
+Class('inherit3::B', 'inherit3.h')
+Class('inherit3::C', 'inherit3.h')
diff --git a/libs/python/pyste/tests/inherit3UT.py b/libs/python/pyste/tests/inherit3UT.py
new file mode 100644
index 000000000..b7dba1e93
--- /dev/null
+++ b/libs/python/pyste/tests/inherit3UT.py
@@ -0,0 +1,27 @@
+# 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)
+import unittest
+from _inherit3 import *
+
+class testInherit3(unittest.TestCase):
+
+ def testIt(self):
+ def testInst(c):
+ self.assertEqual(c.x, 0)
+ self.assertEqual(c.foo(3), 3)
+ x = c.X()
+ self.assertEqual(x.y, 0)
+ self.assertEqual(c.E.i, 0)
+ self.assertEqual(c.E.j, 1)
+ b = B()
+ c = C()
+ testInst(b)
+ testInst(c)
+ self.assertEqual(b.foo(), 1)
+ self.assertEqual(c.foo(), 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/inherit4.h b/libs/python/pyste/tests/inherit4.h
new file mode 100644
index 000000000..a1cecfbc8
--- /dev/null
+++ b/libs/python/pyste/tests/inherit4.h
@@ -0,0 +1,23 @@
+/* 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)
+ */
+namespace inherit4 {
+
+struct A
+{
+ int x;
+};
+
+struct B: A
+{
+ int y;
+};
+
+struct C: B
+{
+ int z;
+};
+
+}
diff --git a/libs/python/pyste/tests/inherit4.pyste b/libs/python/pyste/tests/inherit4.pyste
new file mode 100644
index 000000000..4809e022f
--- /dev/null
+++ b/libs/python/pyste/tests/inherit4.pyste
@@ -0,0 +1,3 @@
+Class('inherit4::A', 'inherit4.h')
+Class('inherit4::B', 'inherit4.h')
+Class('inherit4::C', 'inherit4.h')
diff --git a/libs/python/pyste/tests/inherit4UT.py b/libs/python/pyste/tests/inherit4UT.py
new file mode 100644
index 000000000..f2c75c553
--- /dev/null
+++ b/libs/python/pyste/tests/inherit4UT.py
@@ -0,0 +1,31 @@
+# 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)
+import unittest
+from _inherit4 import *
+
+class TestInherit4(unittest.TestCase):
+
+ def testIt(self):
+ self.assert_(issubclass(B, A))
+ self.assert_(issubclass(C, A))
+ self.assert_(issubclass(C, B))
+ a = A()
+ a.x = 1
+ b = B()
+ b.x = 10
+ b.y = 20
+ c = C()
+ c.x = 100
+ c.y = 200
+ c.z = 300
+ self.assertEqual(a.x, 1)
+ self.assertEqual(b.x, 10)
+ self.assertEqual(b.y, 20)
+ self.assertEqual(c.x, 100)
+ self.assertEqual(c.y, 200)
+ self.assertEqual(c.z, 300)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/inheritUT.py b/libs/python/pyste/tests/inheritUT.py
new file mode 100644
index 000000000..f3e7b4062
--- /dev/null
+++ b/libs/python/pyste/tests/inheritUT.py
@@ -0,0 +1,33 @@
+# 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)
+import unittest
+from _inherit import *
+
+class InheritExampleTest(unittest.TestCase):
+
+ def testIt(self):
+ a = A_int()
+ b = B()
+ self.assert_(isinstance(b, A_int))
+ self.assert_(issubclass(B, A_int))
+ a.set(10)
+ self.assertEqual(a.get(), 10)
+ b.set(1)
+ self.assertEqual(b.go(), 1)
+ self.assertEqual(b.get(), 1)
+
+ d = D()
+ self.assert_(issubclass(D, B))
+ self.assertEqual(d.x, 0)
+ self.assertEqual(d.y, 0)
+ self.assertEqual(d.s, 1)
+ self.assertEqual(D.s, 1)
+ self.assertEqual(d.f1(), 1)
+ self.assertEqual(d.f2(), 2)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/nested.cpp b/libs/python/pyste/tests/nested.cpp
new file mode 100644
index 000000000..6e167ab06
--- /dev/null
+++ b/libs/python/pyste/tests/nested.cpp
@@ -0,0 +1,9 @@
+/* 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)
+ */
+#include "nested.h"
+
+int nested::X::staticXValue = 10;
+int nested::X::Y::staticYValue = 20;
diff --git a/libs/python/pyste/tests/nested.h b/libs/python/pyste/tests/nested.h
new file mode 100644
index 000000000..13ed60856
--- /dev/null
+++ b/libs/python/pyste/tests/nested.h
@@ -0,0 +1,32 @@
+/* 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)
+ */
+
+#ifndef NESTED_H
+#define NESTED_H
+
+namespace nested {
+
+struct X
+{
+ struct Y
+ {
+ int valueY;
+ static int staticYValue;
+ struct Z
+ {
+ int valueZ;
+ };
+ };
+
+ static int staticXValue;
+ int valueX;
+};
+
+typedef X Root;
+
+}
+
+#endif
diff --git a/libs/python/pyste/tests/nested.pyste b/libs/python/pyste/tests/nested.pyste
new file mode 100644
index 000000000..48bb26b55
--- /dev/null
+++ b/libs/python/pyste/tests/nested.pyste
@@ -0,0 +1 @@
+Class('nested::Root', 'nested.h')
diff --git a/libs/python/pyste/tests/nestedUT.py b/libs/python/pyste/tests/nestedUT.py
new file mode 100644
index 000000000..06c1c7beb
--- /dev/null
+++ b/libs/python/pyste/tests/nestedUT.py
@@ -0,0 +1,19 @@
+# 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)
+import unittest
+from _nested import *
+
+class NestedTest(unittest.TestCase):
+
+ def testIt(self):
+ self.assertEqual(Root.staticXValue, 10)
+ self.assertEqual(Root.Y.staticYValue, 20)
+ z = Root.Y.Z()
+ z.valueZ = 3
+ self.assertEqual(z.valueZ, 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/opaque.h b/libs/python/pyste/tests/opaque.h
new file mode 100644
index 000000000..1947830ea
--- /dev/null
+++ b/libs/python/pyste/tests/opaque.h
@@ -0,0 +1,57 @@
+/* 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)
+ */
+#ifndef OPAQUE_H
+#define OPAQUE_H
+
+#include <iostream>
+
+namespace opaque {
+
+
+struct C {
+ C(int v): value(v) {}
+ int value;
+};
+
+
+inline C* new_C()
+{
+ return new C(10);
+}
+
+inline C* new_C_zero()
+{
+ return new C(0);
+}
+
+inline int get(C* c)
+{
+ return c->value;
+}
+
+struct D {
+ D(double v): value(v) {}
+ double value;
+};
+
+struct A
+{
+ D* new_handle()
+ {
+ return new D(3.0);
+ }
+
+ double get(D* d)
+ {
+ return d->value;
+ }
+
+ int f(int x=0) { return x; }
+};
+
+}
+
+#endif
diff --git a/libs/python/pyste/tests/opaque.pyste b/libs/python/pyste/tests/opaque.pyste
new file mode 100644
index 000000000..8180d251c
--- /dev/null
+++ b/libs/python/pyste/tests/opaque.pyste
@@ -0,0 +1,7 @@
+foo = Function('opaque::new_C', 'opaque.h')
+set_policy(foo, return_value_policy(return_opaque_pointer))
+foo = Function('opaque::new_C_zero', 'opaque.h')
+set_policy(foo, return_value_policy(return_opaque_pointer))
+Function('opaque::get', 'opaque.h' )
+A = Class('opaque::A', 'opaque.h')
+set_policy(A.new_handle, return_value_policy(return_opaque_pointer))
diff --git a/libs/python/pyste/tests/opaqueUT.py b/libs/python/pyste/tests/opaqueUT.py
new file mode 100644
index 000000000..0f3e1e073
--- /dev/null
+++ b/libs/python/pyste/tests/opaqueUT.py
@@ -0,0 +1,24 @@
+# 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)
+import unittest
+from _opaque import *
+
+class OpaqueTest(unittest.TestCase):
+
+ def testIt(self):
+
+ c = new_C()
+ self.assertEqual(get(c), 10)
+ c = new_C_zero()
+ self.assertEqual(get(c), 0)
+ a = A()
+ d = a.new_handle()
+ self.assertEqual(a.get(d), 3.0)
+ self.assertEqual(a.f(), 0)
+ self.assertEqual(a.f(3), 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/operators.cpp b/libs/python/pyste/tests/operators.cpp
new file mode 100644
index 000000000..cecdaca0d
--- /dev/null
+++ b/libs/python/pyste/tests/operators.cpp
@@ -0,0 +1,8 @@
+/* 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)
+ */
+#include "operators.h"
+
+double operators::C::x = 10;
diff --git a/libs/python/pyste/tests/operators.h b/libs/python/pyste/tests/operators.h
new file mode 100644
index 000000000..5d3944216
--- /dev/null
+++ b/libs/python/pyste/tests/operators.h
@@ -0,0 +1,52 @@
+/* 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)
+ */
+#ifndef OPERATORS_H
+#define OPERATORS_H
+
+
+namespace operators {
+
+struct C
+{
+ static double x;
+ double value;
+
+ const C operator+(const C other) const
+ {
+ C c;
+ c.value = value + other.value;
+ return c;
+ }
+ operator int() const
+ {
+ return (int)value;
+ }
+
+ double operator()()
+ {
+ return C::x;
+ }
+
+ double operator()(double other)
+ {
+ return C::x + other;
+ }
+
+ operator const char*() { return "C"; }
+};
+
+inline const C operator*(const C& lhs, const C& rhs)
+{
+ C c;
+ c.value = lhs.value * rhs.value;
+ return c;
+}
+
+
+}
+
+
+#endif
diff --git a/libs/python/pyste/tests/operators.pyste b/libs/python/pyste/tests/operators.pyste
new file mode 100644
index 000000000..4ab7a3709
--- /dev/null
+++ b/libs/python/pyste/tests/operators.pyste
@@ -0,0 +1,2 @@
+C = Class('operators::C', 'operators.h')
+#exclude(C.operator['+'])
diff --git a/libs/python/pyste/tests/operatorsUT.py b/libs/python/pyste/tests/operatorsUT.py
new file mode 100644
index 000000000..beb193173
--- /dev/null
+++ b/libs/python/pyste/tests/operatorsUT.py
@@ -0,0 +1,30 @@
+# 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)
+import unittest
+from _operators import *
+
+class OperatorTest(unittest.TestCase):
+
+ def testIt(self):
+ c = C()
+ c.value = 3.0
+ d = C()
+ d.value = 2.0
+ self.assertEqual(c.x, 10)
+ self.assertEqual(C.x, 10)
+ self.assertEqual(C.x, 10)
+ self.assertEqual((c * d).value, 6.0)
+ self.assertEqual((c + d).value, 5.0)
+ self.assertEqual(int(c), 3)
+ self.assertEqual(int(d), 2)
+ self.assertEqual(c(), 10)
+ self.assertEqual(d(), 10)
+ self.assertEqual(c(3.0), 13.0)
+ self.assertEqual(d(6.0), 16.0)
+ self.assertEqual(str(c), "C")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/policiesUT.py b/libs/python/pyste/tests/policiesUT.py
new file mode 100644
index 000000000..7255baeb4
--- /dev/null
+++ b/libs/python/pyste/tests/policiesUT.py
@@ -0,0 +1,67 @@
+# 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)
+import sys
+import unittest
+from Pyste.policies import *
+
+
+#================================================================================
+# PolicicesTest
+#================================================================================
+class PoliciesTest(unittest.TestCase):
+
+ def testReturnInternal(self):
+ 'tests the code from a simple internal_reference'
+
+ x = return_internal_reference(1)
+ self.assertEqual(x.Code(), 'return_internal_reference< 1 >')
+ x = return_internal_reference(3)
+ self.assertEqual(x.Code(), 'return_internal_reference< 3 >')
+
+
+ def testCustodian(self):
+ 'tests the code from a simple custodian_and_ward'
+
+ x = with_custodian_and_ward(1,2)
+ self.assertEqual(x.Code(), 'with_custodian_and_ward< 1, 2 >')
+ x = with_custodian_and_ward(3,4)
+ self.assertEqual(x.Code(), 'with_custodian_and_ward< 3, 4 >')
+
+
+ def testReturnPolicies(self):
+ 'tests all the return_value_policies'
+
+ ret = 'return_value_policy< %s >'
+ x = return_value_policy(reference_existing_object)
+ self.assertEqual(x.Code(), ret % 'reference_existing_object')
+ x = return_value_policy(copy_const_reference)
+ self.assertEqual(x.Code(), ret % 'copy_const_reference')
+ x = return_value_policy(copy_non_const_reference)
+ self.assertEqual(x.Code(), ret % 'copy_non_const_reference')
+ x = return_value_policy(manage_new_object)
+ self.assertEqual(x.Code(), ret % 'manage_new_object')
+ x = return_value_policy(return_opaque_pointer)
+ self.assertEqual(x.Code(), ret % 'return_opaque_pointer')
+
+ def testReturnWithCustodiam(self):
+ 'test the mix of return_internal with custodian'
+
+ x = return_internal_reference(1, with_custodian_and_ward(3,2))
+ self.assertEqual(
+ x.Code(),
+ 'return_internal_reference< 1, with_custodian_and_ward< 3, 2 > >')
+
+
+ def testReturnPoliciesWithInternal(self):
+ 'test the mix of return_internal with return_policy'
+
+ x = return_internal_reference(1, return_value_policy(manage_new_object))
+ self.assertEqual(
+ x.Code(),
+ 'return_internal_reference< 1, return_value_policy< manage_new_object > >')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/runtests.py b/libs/python/pyste/tests/runtests.py
new file mode 100644
index 000000000..4bf83b345
--- /dev/null
+++ b/libs/python/pyste/tests/runtests.py
@@ -0,0 +1,21 @@
+# 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)
+#!/usr/bin/python
+
+import sys
+sys.path.append('../src/Pyste')
+import unittest
+import os.path
+from glob import glob
+
+if __name__ == '__main__':
+ loader = unittest.defaultTestLoader
+ tests = []
+ for name in glob('*UT.py'):
+ module = __import__(os.path.splitext(name)[0])
+ tests.append(loader.loadTestsFromModule(module))
+ runner = unittest.TextTestRunner()
+ result = runner.run(unittest.TestSuite(tests))
+ sys.exit(not result.wasSuccessful())
diff --git a/libs/python/pyste/tests/smart_ptr.h b/libs/python/pyste/tests/smart_ptr.h
new file mode 100644
index 000000000..b230b9179
--- /dev/null
+++ b/libs/python/pyste/tests/smart_ptr.h
@@ -0,0 +1,50 @@
+/* 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)
+ */
+
+#ifndef SMART_PTR_H
+#define SMART_PTR_H
+
+
+#include <memory>
+#include <boost/shared_ptr.hpp>
+
+namespace smart_ptr {
+
+struct C
+{
+ int value;
+};
+
+inline boost::shared_ptr<C> NewC() { return boost::shared_ptr<C>( new C() ); }
+
+struct D
+{
+ boost::shared_ptr<C> Get() { return ptr; }
+ void Set( boost::shared_ptr<C> c ) { ptr = c; }
+private:
+ boost::shared_ptr<C> ptr;
+};
+
+inline std::auto_ptr<D> NewD() { return std::auto_ptr<D>( new D() ); }
+
+
+// test an abstract class
+struct A
+{
+ virtual int f() = 0;
+};
+
+struct B: A
+{
+ virtual int f(){ return 1; }
+};
+
+inline boost::shared_ptr<A> NewA() { return boost::shared_ptr<A>(new B()); }
+inline int GetA(boost::shared_ptr<A> a) { return a->f(); }
+
+}
+
+#endif
diff --git a/libs/python/pyste/tests/smart_ptr.pyste b/libs/python/pyste/tests/smart_ptr.pyste
new file mode 100644
index 000000000..cfbdd81ae
--- /dev/null
+++ b/libs/python/pyste/tests/smart_ptr.pyste
@@ -0,0 +1,13 @@
+C = Class('smart_ptr::C', 'smart_ptr.h')
+use_shared_ptr(C)
+
+D = Class('smart_ptr::D', 'smart_ptr.h')
+use_auto_ptr(D)
+
+A = Class('smart_ptr::A', 'smart_ptr.h')
+use_shared_ptr(A)
+
+Function('smart_ptr::NewC', 'smart_ptr.h')
+Function('smart_ptr::NewD', 'smart_ptr.h')
+Function('smart_ptr::NewA', 'smart_ptr.h')
+Function('smart_ptr::GetA', 'smart_ptr.h')
diff --git a/libs/python/pyste/tests/smart_ptrUT.py b/libs/python/pyste/tests/smart_ptrUT.py
new file mode 100644
index 000000000..9d81f08dd
--- /dev/null
+++ b/libs/python/pyste/tests/smart_ptrUT.py
@@ -0,0 +1,22 @@
+# 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)
+import unittest
+from _smart_ptr import *
+
+class BasicExampleTest(unittest.TestCase):
+
+ def testIt(self):
+ c = NewC()
+ d = NewD()
+ c.value = 3
+ d.Set(c)
+ c1 = d.Get()
+ c1.value = 6
+ self.assertEqual(c.value, 6)
+ a = NewA()
+ self.assertEqual(GetA(a), 1)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/templates.h b/libs/python/pyste/tests/templates.h
new file mode 100644
index 000000000..7258e91c7
--- /dev/null
+++ b/libs/python/pyste/tests/templates.h
@@ -0,0 +1,15 @@
+/* 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)
+ */
+namespace templates {
+
+template <class T>
+struct Point
+{
+ T x;
+ T y;
+};
+
+}
diff --git a/libs/python/pyste/tests/templates.pyste b/libs/python/pyste/tests/templates.pyste
new file mode 100644
index 000000000..77eaceaa3
--- /dev/null
+++ b/libs/python/pyste/tests/templates.pyste
@@ -0,0 +1,8 @@
+Point = Template('templates::Point', 'templates.h')
+rename(Point.x, 'i')
+rename(Point.y, 'j')
+IPoint = Point('int')
+FPoint = Point('double', 'FPoint')
+rename(IPoint, 'IPoint')
+rename(IPoint.x, 'x')
+rename(IPoint.y, 'y')
diff --git a/libs/python/pyste/tests/templatesUT.py b/libs/python/pyste/tests/templatesUT.py
new file mode 100644
index 000000000..0c4b08b50
--- /dev/null
+++ b/libs/python/pyste/tests/templatesUT.py
@@ -0,0 +1,30 @@
+# 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)
+import unittest
+from _templates import *
+
+class TemplatesTest(unittest.TestCase):
+
+ def testIt(self):
+ fp = FPoint()
+ fp.i = 3.0
+ fp.j = 4.0
+ ip = IPoint()
+ ip.x = 10
+ ip.y = 3
+
+ self.assertEqual(fp.i, 3.0)
+ self.assertEqual(fp.j, 4.0)
+ self.assertEqual(ip.x, 10)
+ self.assertEqual(ip.y, 3)
+ self.assertEqual(type(fp.i), float)
+ self.assertEqual(type(fp.j), float)
+ self.assertEqual(type(ip.x), int)
+ self.assertEqual(type(ip.y), int)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/test_all.py b/libs/python/pyste/tests/test_all.py
new file mode 100644
index 000000000..ba3c54dee
--- /dev/null
+++ b/libs/python/pyste/tests/test_all.py
@@ -0,0 +1,140 @@
+#!/usr/bin/python
+# 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)
+
+import os
+import glob
+import shutil
+import sys
+import time
+
+#=============================================================================
+# win32 configuration
+#=============================================================================
+if sys.platform == 'win32':
+
+ includes = '-ID:/programming/libraries/boost-cvs/boost -ID:/Bin/Python/include'
+ build_pyste_cmd = 'python ../src/Pyste/pyste.py --pyste-ns=pyste --cache-dir=cache %s ' % includes
+ compile_single_cmd = 'cl /nologo /GR /GX -c %s -I. ' % includes
+ link_single_cmd = 'link /nologo /DLL '\
+ '/libpath:D:/programming/libraries/boost-cvs/lib /libpath:D:/Bin/Python/libs '\
+ 'boost_python.lib python24.lib /out:_%s.dll '
+ obj_ext = 'obj'
+
+#=============================================================================
+# linux configuration
+#=============================================================================
+elif sys.platform == 'linux2':
+
+ build_pyste_cmd = 'python ../src/Pyste/pyste.py -I. '
+ compile_single_cmd = 'g++ -shared -c -I. -I/usr/include/python2.4 '
+ link_single_cmd = 'g++ -shared -o _%s.so -lboost_python '
+ obj_ext = 'o'
+
+
+
+def build_pyste(multiple, module):
+ rest = '%s --module=_%s %s.pyste' % (multiple, module, module)
+ execute(build_pyste_cmd + rest)
+
+
+def compile_single(module):
+ module_obj = ''
+ if os.path.isfile(module+'.cpp'):
+ execute(compile_single_cmd + module+'.cpp')
+ module_obj = module + '.' + obj_ext
+ execute(compile_single_cmd + ('_%s.cpp' % module))
+ link = link_single_cmd % module
+ execute(link + ('_%s.%s ' % (module, obj_ext)) + module_obj)
+
+
+def compile_multiple(module):
+ module_obj = ''
+ if os.path.isfile(module+'.cpp'):
+ execute(compile_single_cmd + module+'.cpp')
+ module_obj = module + '.' + obj_ext
+ files = glob.glob('_%s/*.cpp' % module)
+ for f in files:
+ execute(compile_single_cmd + f)
+ def basename(name):
+ return os.path.basename(os.path.splitext(name)[0])
+ objs = [basename(x) + '.' + obj_ext for x in files]
+ objs.append(module_obj)
+ execute((link_single_cmd % module) + ' '.join(objs))
+
+
+def execute(cmd):
+ os.system(cmd)
+
+
+def run_tests():
+ if os.system('python runtests.py') != 0:
+ raise RuntimeError, 'tests failed'
+
+
+def cleanup():
+ modules = get_modules()
+ extensions = '*.dll *.pyc *.obj *.exp *.lib *.o *.so'
+ files = []
+ for module in modules:
+ files.append('_' + module + '.cpp')
+ for ext in extensions.split():
+ files += glob.glob(ext)
+ files.append('build.log')
+ for file in files:
+ try:
+ os.remove(file)
+ except OSError: pass
+
+ for module in modules:
+ try:
+ shutil.rmtree('_' + module)
+ except OSError: pass
+
+
+def main(multiple, module=None):
+ if module is None:
+ modules = get_modules()
+ else:
+ modules = [module]
+
+ start = time.clock()
+ for module in modules:
+ build_pyste(multiple, module)
+ print '-'*50
+ print 'Building pyste files: %0.2f seconds' % (time.clock()-start)
+ print
+
+ start = time.clock()
+ for module in modules:
+ if multiple:
+ compile_multiple(module)
+ else:
+ compile_single(module)
+ print '-'*50
+ print 'Compiling files: %0.2f seconds' % (time.clock()-start)
+ print
+ if len(modules) == 1:
+ os.system('python %sUT.py' % modules[0])
+ else:
+ run_tests()
+ #cleanup()
+
+
+def get_modules():
+ def getname(file):
+ return os.path.splitext(os.path.basename(file))[0]
+ return [getname(x) for x in glob.glob('*.pyste')]
+
+if __name__ == '__main__':
+ if len(sys.argv) > 1:
+ module = sys.argv[1]
+ else:
+ module = None
+ try:
+# main('--multiple', module)
+ main('', module)
+ except RuntimeError, e:
+ print e
diff --git a/libs/python/pyste/tests/vars.cpp b/libs/python/pyste/tests/vars.cpp
new file mode 100644
index 000000000..e2abcd332
--- /dev/null
+++ b/libs/python/pyste/tests/vars.cpp
@@ -0,0 +1,12 @@
+/* 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)
+ */
+#include "vars.h"
+
+const Color black = Color(0, 0, 0);
+const Color red = Color(255, 0, 0);
+const Color green = Color(0, 255, 0);
+const Color blue = Color(0, 0, 255);
+Color in_use = black;
diff --git a/libs/python/pyste/tests/vars.h b/libs/python/pyste/tests/vars.h
new file mode 100644
index 000000000..24e87d802
--- /dev/null
+++ b/libs/python/pyste/tests/vars.h
@@ -0,0 +1,24 @@
+/* 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)
+ */
+
+struct Color
+{
+ Color(int r_ = 0, int g_ = 0, int b_ = 0):
+ r(r_), g(g_), b(b_)
+ {}
+ Color( const Color &c):
+ r(c.r), g(c.g), b(c.b)
+ {}
+ int r;
+ int g;
+ int b;
+};
+
+extern const Color black;
+extern const Color red;
+extern const Color green;
+extern const Color blue;
+extern Color in_use;
diff --git a/libs/python/pyste/tests/vars.pyste b/libs/python/pyste/tests/vars.pyste
new file mode 100644
index 000000000..3fd9d689d
--- /dev/null
+++ b/libs/python/pyste/tests/vars.pyste
@@ -0,0 +1 @@
+AllFromHeader('vars.h')
diff --git a/libs/python/pyste/tests/varsUT.py b/libs/python/pyste/tests/varsUT.py
new file mode 100644
index 000000000..4c32cbb2f
--- /dev/null
+++ b/libs/python/pyste/tests/varsUT.py
@@ -0,0 +1,22 @@
+# 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)
+import unittest
+import _vars
+
+
+class VarsTest(unittest.TestCase):
+
+ def testIt(self):
+ def testColor(c, r, g, b):
+ self.assertEqual(c.r, r)
+ self.assertEqual(c.g, g)
+ self.assertEqual(c.b, b)
+ testColor(_vars.black, 0, 0, 0)
+ testColor(_vars.red, 255, 0, 0)
+ testColor(_vars.green, 0, 255, 0)
+ testColor(_vars.blue, 0, 0, 255)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/virtual.cpp b/libs/python/pyste/tests/virtual.cpp
new file mode 100644
index 000000000..070d9d346
--- /dev/null
+++ b/libs/python/pyste/tests/virtual.cpp
@@ -0,0 +1,75 @@
+/* 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)
+ */
+
+// Includes ====================================================================
+#include <boost/python.hpp>
+#include <virtual.h>
+
+// Using =======================================================================
+using namespace boost::python;
+
+// Declarations ================================================================
+
+
+namespace {
+
+
+struct virtual_C_Wrapper: virtual_::C
+{
+ virtual_C_Wrapper(PyObject* self_, const virtual_::C & p0):
+ virtual_::C(p0), self(self_) {}
+
+ virtual_C_Wrapper(PyObject* self_):
+ virtual_::C(), self(self_) {}
+
+ int f() {
+ return call_method< int >(self, "f");
+ }
+
+ int default_f() {
+ return virtual_::C::f();
+ }
+
+ void bar(int p0) {
+ call_method< void >(self, "bar", p0);
+ }
+
+ void default_bar(int p0) {
+ virtual_::C::bar(p0);
+ }
+
+ void bar(char * p0) {
+ call_method< void >(self, "bar", p0);
+ }
+
+ void default_bar(char * p0) {
+ virtual_::C::bar(p0);
+ }
+
+ int f_abs() {
+ return call_method< int >(self, "f_abs");
+ }
+
+ PyObject* self;
+};
+
+
+
+}// namespace
+
+
+// Module ======================================================================
+BOOST_PYTHON_MODULE(virtual)
+{
+ class_< virtual_::C, boost::noncopyable, virtual_C_Wrapper >("C", init< >())
+ .def("get_name", &virtual_::C::get_name)
+ .def("f", &virtual_::C::f, &virtual_C_Wrapper::default_f)
+ .def("bar", (void (virtual_::C::*)(int) )&virtual_::C::bar, (void (virtual_C_Wrapper::*)(int))&virtual_C_Wrapper::default_bar)
+ .def("bar", (void (virtual_::C::*)(char *) )&virtual_::C::bar, (void (virtual_C_Wrapper::*)(char *))&virtual_C_Wrapper::default_bar)
+ ;
+
+ def("call_f", &virtual_::call_f);
+}
diff --git a/libs/python/pyste/tests/virtual.h b/libs/python/pyste/tests/virtual.h
new file mode 100644
index 000000000..d0bb194a1
--- /dev/null
+++ b/libs/python/pyste/tests/virtual.h
@@ -0,0 +1,41 @@
+/* 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)
+ */
+namespace virtual_ {
+
+struct C
+{
+public:
+ virtual int f()
+ {
+ return f_abs();
+ }
+
+ virtual void bar(int) {}
+ virtual void bar(char*) {}
+
+ const char* get_name()
+ {
+ return name();
+ }
+ virtual int dummy() { return 0; }
+
+protected:
+ virtual int f_abs() = 0;
+
+private:
+ virtual const char* name() { return "C"; }
+};
+
+struct D
+{
+ virtual int dummy() { return 0; }
+};
+
+inline int call_f(C& c) { return c.f(); }
+inline int call_dummy(C* c) { return c->dummy(); }
+inline int call_dummy(D* d) { return d->dummy(); }
+
+}
diff --git a/libs/python/pyste/tests/virtual.pyste b/libs/python/pyste/tests/virtual.pyste
new file mode 100644
index 000000000..ef9664124
--- /dev/null
+++ b/libs/python/pyste/tests/virtual.pyste
@@ -0,0 +1,6 @@
+C = Class('virtual_::C', 'virtual.h')
+final(C.dummy)
+D = Class('virtual_::D', 'virtual.h')
+final(D.dummy)
+Function('virtual_::call_f', 'virtual.h')
+Function('virtual_::call_dummy', 'virtual.h')
diff --git a/libs/python/pyste/tests/virtual2.h b/libs/python/pyste/tests/virtual2.h
new file mode 100644
index 000000000..a6677ad16
--- /dev/null
+++ b/libs/python/pyste/tests/virtual2.h
@@ -0,0 +1,34 @@
+/* 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)
+ */
+
+namespace virtual2 {
+
+struct A
+{
+ virtual int f() { return 0; }
+ virtual int f1() { return 10; }
+ virtual A* make_new() { return new A; }
+};
+
+struct B: A
+{
+ virtual int f() { return 1; }
+ virtual int f2() { return 20; }
+ virtual A* make_new() { return new B; }
+};
+
+inline int call_fs(A*a)
+{
+ int r = a->f1();
+ B* b = dynamic_cast<B*>(a);
+ return r + b->f2();
+}
+
+inline int call_f(A* a)
+{
+ return a->f();
+}
+}
diff --git a/libs/python/pyste/tests/virtual2.pyste b/libs/python/pyste/tests/virtual2.pyste
new file mode 100644
index 000000000..785b819c8
--- /dev/null
+++ b/libs/python/pyste/tests/virtual2.pyste
@@ -0,0 +1,6 @@
+A = Class('virtual2::A', 'virtual2.h')
+set_policy(A.make_new, return_value_policy(manage_new_object))
+B = Class('virtual2::B', 'virtual2.h')
+set_policy(B.make_new, return_value_policy(manage_new_object))
+Function('virtual2::call_fs', 'virtual2.h')
+Function('virtual2::call_f', 'virtual2.h')
diff --git a/libs/python/pyste/tests/virtual2UT.py b/libs/python/pyste/tests/virtual2UT.py
new file mode 100644
index 000000000..312277d26
--- /dev/null
+++ b/libs/python/pyste/tests/virtual2UT.py
@@ -0,0 +1,40 @@
+# 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)
+
+import unittest
+from _virtual2 import *
+
+class Virtual2Test(unittest.TestCase):
+
+ def testIt(self):
+ a = A()
+ self.assertEqual(a.f1(), 10)
+ b = B()
+ self.assertEqual(b.f1(), 10)
+ self.assertEqual(b.f2(), 20)
+ self.assertEqual(call_fs(b), 30)
+ self.assertEqual(call_f(a), 0)
+ self.assertEqual(call_f(b), 1)
+ nb = b.make_new()
+ na = a.make_new()
+ self.assertEqual(na.f1(), 10)
+ self.assertEqual(nb.f1(), 10)
+ self.assertEqual(nb.f2(), 20)
+ self.assertEqual(call_fs(nb), 30)
+ self.assertEqual(call_f(na), 0)
+ self.assertEqual(call_f(nb), 1)
+ class C(B):
+ def f1(self): return 1
+ def f2(self): return 2
+ def f(self): return 100
+
+ c = C()
+ self.assertEqual(call_fs(c), 3)
+ self.assertEqual(call_fs(c), 3)
+ self.assertEqual(call_f(c), 100)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/virtualUT.py b/libs/python/pyste/tests/virtualUT.py
new file mode 100644
index 000000000..deff68189
--- /dev/null
+++ b/libs/python/pyste/tests/virtualUT.py
@@ -0,0 +1,55 @@
+# 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)
+import unittest
+from _virtual import *
+
+class VirtualTest(unittest.TestCase):
+
+ def testIt(self):
+
+ class E(C):
+ def f_abs(self):
+ return 3
+ def dummy(self):
+ # override should not work
+ return 100
+
+ class F(C):
+ def f(self):
+ return 10
+ def name(self):
+ return 'F'
+
+ class G(D):
+ def dummy(self):
+ # override should not work
+ return 100
+
+ e = E()
+ f = F()
+
+ self.assertEqual(e.f(), 3)
+ self.assertEqual(call_f(e), 3)
+ self.assertEqual(f.f(), 10)
+ self.assertEqual(call_f(f), 10)
+ self.assertEqual(e.get_name(), 'C')
+ #self.assertEqual(e.get_name(), 'E') check this later
+
+ c = C()
+ c.bar(1) # ok
+ c.bar('a') # ok
+ self.assertRaises(TypeError, c.bar, 1.0)
+
+ # test no_overrides
+ d = G()
+ self.assertEqual(e.dummy(), 100)
+ self.assertEqual(call_dummy(e), 0)
+ self.assertEqual(d.dummy(), 100)
+ self.assertEqual(call_dummy(d), 0)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/wrappertest.h b/libs/python/pyste/tests/wrappertest.h
new file mode 100644
index 000000000..2304fd843
--- /dev/null
+++ b/libs/python/pyste/tests/wrappertest.h
@@ -0,0 +1,51 @@
+/* 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)
+ */
+#ifndef WRAPPER_TEST
+#define WRAPPER_TEST
+
+
+#include <vector>
+
+namespace wrappertest {
+
+inline std::vector<int> Range(int count)
+{
+ std::vector<int> v;
+ v.reserve(count);
+ for (int i = 0; i < count; ++i){
+ v.push_back(i);
+ }
+ return v;
+}
+
+
+struct C
+{
+ C() {}
+
+ std::vector<int> Mul(int value)
+ {
+ std::vector<int> res;
+ res.reserve(value);
+ std::vector<int>::const_iterator it;
+ std::vector<int> v(Range(value));
+ for (it = v.begin(); it != v.end(); ++it){
+ res.push_back(*it * value);
+ }
+ return res;
+ }
+};
+
+
+struct A
+{
+ virtual int f() { return 1; };
+};
+
+inline int call_foo(A* a){ return a->f(); }
+}
+#endif
+
diff --git a/libs/python/pyste/tests/wrappertest.pyste b/libs/python/pyste/tests/wrappertest.pyste
new file mode 100644
index 000000000..12ba47b6b
--- /dev/null
+++ b/libs/python/pyste/tests/wrappertest.pyste
@@ -0,0 +1,21 @@
+Include('wrappertest_wrappers.h')
+
+f = Function('wrappertest::Range', 'wrappertest.h')
+set_wrapper(f, 'RangeWrapper')
+
+mul = Wrapper('MulWrapper',
+'''
+list MulWrapper(wrappertest::C& c, int value){
+ return VectorToList(c.Mul(value));
+}
+'''
+)
+
+C = Class('wrappertest::C', 'wrappertest.h')
+set_wrapper(C.Mul, mul)
+
+
+A = Class('wrappertest::A', 'wrappertest.h')
+set_wrapper(A.f, 'f_wrapper')
+
+Function('wrappertest::call_foo', 'wrappertest.h')
diff --git a/libs/python/pyste/tests/wrappertestUT.py b/libs/python/pyste/tests/wrappertestUT.py
new file mode 100644
index 000000000..d770408b7
--- /dev/null
+++ b/libs/python/pyste/tests/wrappertestUT.py
@@ -0,0 +1,24 @@
+# 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)
+import unittest
+from _wrappertest import *
+
+class WrapperTest(unittest.TestCase):
+
+ def testIt(self):
+ self.assertEqual(Range(10), range(10))
+ self.assertEqual(C().Mul(10), [x*10 for x in range(10)])
+
+ a = A()
+ self.assertEqual(a.f(), 10)
+ self.assertEqual(call_foo(a), 10)
+ class D(A):
+ def f(self): return 2
+ d = D()
+ self.assertEqual(d.f(), 2)
+ self.assertEqual(call_foo(d), 2)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/libs/python/pyste/tests/wrappertest_wrappers.h b/libs/python/pyste/tests/wrappertest_wrappers.h
new file mode 100644
index 000000000..31570a051
--- /dev/null
+++ b/libs/python/pyste/tests/wrappertest_wrappers.h
@@ -0,0 +1,33 @@
+/* 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)
+ */
+#ifndef WRAPPER_TEST_WRAPPERS
+#define WRAPPER_TEST_WRAPPERS
+
+#include <vector>
+#include <boost/python.hpp>
+#include "wrappertest.h"
+
+using namespace boost::python;
+
+template <class T>
+list VectorToList(const std::vector<T> & v)
+{
+ list res;
+ typename std::vector<T>::const_iterator it;
+ for(it = v.begin(); it != v.end(); ++it){
+ res.append(*it);
+ }
+ Py_XINCREF(res.ptr());
+ return res;
+}
+
+inline list RangeWrapper(int count){
+ return VectorToList(wrappertest::Range(count));
+}
+
+inline int f_wrapper(wrappertest::A*) { return 10; }
+
+#endif