2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Ralf W. Grosse-Kunstleve
0d6b042c4c Windows2000 mods.
[SVN r10727]
2001-07-31 07:01:27 +00:00
Ralf W. Grosse-Kunstleve
55a7884912 Small doc update.
[SVN r10726]
2001-07-31 06:27:06 +00:00
Ralf W. Grosse-Kunstleve
2566e1dd3a Trivial fixes for Python 2.2a1. (One real problem remains...)
[SVN r10664]
2001-07-19 00:23:06 +00:00
Ralf W. Grosse-Kunstleve
9bca6982a4 doctest tests test_richcmp?.py, make test updated.
[SVN r10662]
2001-07-18 21:33:47 +00:00
Ralf W. Grosse-Kunstleve
c7e12ecf3d richcmp3.cpp significantly simplified.
[SVN r10660]
2001-07-18 15:24:41 +00:00
Ralf W. Grosse-Kunstleve
5031479fa2 test_richcmp1.py now works with vc60.
[SVN r10657]
2001-07-18 13:16:51 +00:00
Ralf W. Grosse-Kunstleve
fc9a6ac369 New: richcmp.html, richcmp1.cpp, richcmp2.cpp, richcmp3.cpp.
Still needs more testing. richcmp1.cpp does not compile under windows.


[SVN r10656]
2001-07-18 03:14:48 +00:00
Ralf W. Grosse-Kunstleve
905074542e VC60 workaround, to suppress bogus warning.
[SVN r10629]
2001-07-16 00:10:27 +00:00
Ralf W. Grosse-Kunstleve
b7957da50a gen_*.py updated
[SVN r10625]
2001-07-15 10:48:51 +00:00
Ralf W. Grosse-Kunstleve
1b1620b62a Tested with Python 1.5.2 and Python 2.1.1c1
[SVN r10624]
2001-07-15 10:36:49 +00:00
Ralf W. Grosse-Kunstleve
0ed5af25a7 Tested: all compilers & python 1.5.2, all unix & python 2.1
[SVN r10623]
2001-07-15 09:41:09 +00:00
nobody
1dbcf12502 This commit was manufactured by cvs2svn to create branch
'boost_python_richcmp'.

[SVN r10595]
2001-07-12 15:31:16 +00:00
nobody
10c2fbd63a This commit was manufactured by cvs2svn to create branch
'iter-adaptor-and-categories'.

[SVN r10453]
2001-06-27 22:12:20 +00:00
Dave Abrahams
4328ae1d8d Updates for Boost.Build
[SVN r10403]
2001-06-22 22:36:00 +00:00
Ralf W. Grosse-Kunstleve
88372000b5 fixes due to Jens Maurer (merged from branch boost_python_friend_fixes)
[SVN r10395]
2001-06-22 00:49:58 +00:00
Dave Abrahams
081150b477 Quick Borland fix
[SVN r10391]
2001-06-21 23:40:04 +00:00
Dave Abrahams
1364b97b88 A small Borland fix
[SVN r10390]
2001-06-21 23:39:30 +00:00
Dave Abrahams
7c33a46a76 A small fix for Borland
[SVN r10389]
2001-06-21 23:38:42 +00:00
Ralf W. Grosse-Kunstleve
8b88e9f727 define changed to enable Silicon Graphics gcc compilation.
[SVN r10378]
2001-06-21 20:49:41 +00:00
Ralf W. Grosse-Kunstleve
91f0728b55 Minor fix, thanks to Jens Maurer.
[SVN r10377]
2001-06-21 20:46:26 +00:00
Dave Abrahams
7a71cea92a updated ILU links thanks to Scott Langley
[SVN r10355]
2001-06-18 12:11:46 +00:00
Dave Abrahams
29a855813d fixed typo
[SVN r10240]
2001-05-28 20:14:25 +00:00
Dave Abrahams
9b602d16b4 initial import
[SVN r8327]
2000-11-26 15:49:26 +00:00
51 changed files with 1255 additions and 112 deletions

View File

@@ -52,6 +52,13 @@ bpl_exa + "/tst_dvect2.py",
bpl_exa + "/tst_ivect1.py",
bpl_exa + "/tst_ivect2.py",
bpl_exa + "/test_cross_module.py",
bpl_exa + "/vector_wrapper.h",
bpl_exa + "/richcmp1.cpp",
bpl_exa + "/richcmp2.cpp",
bpl_exa + "/richcmp3.cpp",
bpl_exa + "/test_richcmp1.py",
bpl_exa + "/test_richcmp2.py",
bpl_exa + "/test_richcmp3.py",
)
defs = (
@@ -68,6 +75,9 @@ defs = (
"noncopyable_import",
"ivect",
"dvect",
"richcmp1",
"richcmp2",
"richcmp3",
)
if (__name__ == "__main__"):

View File

@@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost
PYEXE=/usr/local/Python-1.5.2/bin/python
PYINC=-I/usr/local/Python-1.5.2/include/python1.5
#PYEXE=/usr/local/Python-2.0/bin/python
#PYINC=-I/usr/local/Python-2.0/include/python2.0
#PYEXE=/usr/local/Python-2.1/bin/python
#PYINC=-I/usr/local/Python-2.1/include/python2.1
STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers
STDOPTS=
@@ -46,7 +46,8 @@ DEPOBJ=$(OBJ) \
do_it_yourself_converters.o \
pickle1.o pickle2.o pickle3.o \
noncopyable_export.o noncopyable_import.o \
ivect.o dvect.o
ivect.o dvect.o \
richcmp1.o richcmp2.o richcmp3.o
.SUFFIXES: .o .cpp
@@ -58,7 +59,8 @@ all: libboost_python.a \
do_it_yourself_converters.so \
pickle1.so pickle2.so pickle3.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so
ivect.so dvect.so \
richcmp1.so richcmp2.so richcmp3.so
libboost_python.a: $(OBJ)
rm -f libboost_python.a
@@ -105,6 +107,15 @@ ivect.so: $(OBJ) ivect.o
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
richcmp1.so: $(OBJ) richcmp1.o
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
richcmp2.so: $(OBJ) richcmp2.o
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
richcmp3.so: $(OBJ) richcmp3.o
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -119,6 +130,9 @@ test:
$(PYEXE) test_pickle2.py
$(PYEXE) test_pickle3.py
$(PYEXE) test_cross_module.py
$(PYEXE) test_richcmp1.py
$(PYEXE) test_richcmp2.py
$(PYEXE) test_richcmp3.py
clean:
rm -f $(OBJ) libboost_python.a libboost_python.a.input
@@ -135,6 +149,9 @@ clean:
rm -f noncopyable_import.o noncopyable_import.so
rm -f ivect.o ivect.so
rm -f dvect.o dvect.so
rm -f richcmp1.o richcmp1.so
rm -f richcmp2.o richcmp2.so
rm -f richcmp3.o richcmp3.so
rm -f so_locations *.pyc
rm -rf ii_files

View File

@@ -17,14 +17,14 @@
ROOT=$(HOME)
BOOST=$(ROOT)/boost
PYEXE=/usr/bin/python
PYEXE=PYTHONPATH=. /usr/bin/python
PYINC=-I/usr/include/python1.5
#PYEXE=/usr/local/Python-1.5.2/bin/python
#PYINC=-I/usr/local/Python-1.5.2/include/python1.5
#PYEXE=/usr/local/Python-2.0/bin/python
#PYINC=-I/usr/local/Python-2.0/include/python2.0
#PYEXE=/usr/local/Python-2.1/bin/python
#PYINC=-I/usr/local/Python-2.1/include/python2.1
STDOPTS=-ftemplate-depth-21
STDOPTS=-fPIC -ftemplate-depth-21
WARNOPTS=
OPTOPTS=-g
@@ -33,7 +33,7 @@ CPPOPTS=$(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
$(STDOPTS) $(WARNOPTS) $(OPTOPTS)
MAKEDEP=-M
LD=g++
LD=$(CPP)
LDOPTS=-shared
OBJ=classes.o conversions.o extension_class.o functions.o \
@@ -47,7 +47,8 @@ DEPOBJ=$(OBJ) \
do_it_yourself_converters.o \
pickle1.o pickle2.o pickle3.o \
noncopyable_export.o noncopyable_import.o \
ivect.o dvect.o
ivect.o dvect.o \
richcmp1.o richcmp2.o richcmp3.o
.SUFFIXES: .o .cpp
@@ -59,7 +60,8 @@ all: libboost_python.a \
do_it_yourself_converters.so \
pickle1.so pickle2.so pickle3.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so
ivect.so dvect.so \
richcmp1.so richcmp2.so richcmp3.so
libboost_python.a: $(OBJ)
rm -f libboost_python.a
@@ -106,6 +108,15 @@ ivect.so: $(OBJ) ivect.o
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
richcmp1.so: $(OBJ) richcmp1.o
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
richcmp2.so: $(OBJ) richcmp2.o
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
richcmp3.so: $(OBJ) richcmp3.o
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -120,6 +131,9 @@ test:
$(PYEXE) test_pickle2.py
$(PYEXE) test_pickle3.py
$(PYEXE) test_cross_module.py
$(PYEXE) test_richcmp1.py
$(PYEXE) test_richcmp2.py
$(PYEXE) test_richcmp3.py
clean:
rm -f $(OBJ) libboost_python.a libboost_python.a.input
@@ -136,6 +150,9 @@ clean:
rm -f noncopyable_import.o noncopyable_import.so
rm -f ivect.o ivect.so
rm -f dvect.o dvect.so
rm -f richcmp1.o richcmp1.so
rm -f richcmp2.o richcmp2.so
rm -f richcmp3.o richcmp3.so
rm -f so_locations *.pyc
softlinks:

View File

@@ -62,10 +62,11 @@ all: libboost_python.a \
do_it_yourself_converters.pyd \
pickle1.pyd pickle2.pyd pickle3.pyd \
noncopyable_export.pyd noncopyable_import.pyd \
ivect.pyd dvect.pyd
ivect.pyd dvect.pyd \
richcmp1.pyd richcmp2.pyd richcmp3.pyd
libboost_python.a: $(OBJ)
del libboost_python.a
-del libboost_python.a
ar r libboost_python.a $(OBJ)
DLLWRAPOPTS=-s --driver-name g++ -s \
@@ -149,6 +150,24 @@ dvect.pyd: $(OBJ) dvect.o
--def dvect.def \
$(OBJ) dvect.o $(PYLIB)
richcmp1.pyd: $(OBJ) richcmp1.o
dllwrap $(DLLWRAPOPTS) \
--dllname richcmp1.pyd \
--def richcmp1.def \
$(OBJ) richcmp1.o $(PYLIB)
richcmp2.pyd: $(OBJ) richcmp2.o
dllwrap $(DLLWRAPOPTS) \
--dllname richcmp2.pyd \
--def richcmp2.def \
$(OBJ) richcmp2.o $(PYLIB)
richcmp3.pyd: $(OBJ) richcmp3.o
dllwrap $(DLLWRAPOPTS) \
--dllname richcmp3.pyd \
--def richcmp3.def \
$(OBJ) richcmp3.o $(PYLIB)
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -163,12 +182,15 @@ test:
$(PYEXE) test_pickle2.py
$(PYEXE) test_pickle3.py
$(PYEXE) test_cross_module.py
$(PYEXE) test_richcmp1.py
$(PYEXE) test_richcmp2.py
$(PYEXE) test_richcmp3.py
clean:
del *.o
del *.a
del *.pyd
del *.pyc
-del *.o
-del *.a
-del *.pyd
-del *.pyc
softlinks:
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks

View File

@@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost
PYEXE=/usr/local/Python-1.5.2/bin/python
PYINC=-I/usr/local/Python-1.5.2/include/python1.5
#PYEXE=/usr/local/Python-2.0/bin/python
#PYINC=-I/usr/local/Python-2.0/include/python2.0
#PYEXE=/usr/local/Python-2.1/bin/python
#PYINC=-I/usr/local/Python-2.1/include/python2.1
#STLPORTINC=-I/usr/local/STLport-4.1b3/stlport
#STLPORTINC=-I/usr/local/STLport-4.1b4/stlport
#STLPORTOPTS= \
@@ -57,7 +57,8 @@ DEPOBJ=$(OBJ) \
do_it_yourself_converters.o \
pickle1.o pickle2.o pickle3.o \
noncopyable_export.o noncopyable_import.o \
ivect.o dvect.o
ivect.o dvect.o \
richcmp1.o richcmp2.o richcmp3.o
.SUFFIXES: .o .cpp
@@ -69,7 +70,8 @@ all: libboost_python.a \
do_it_yourself_converters.so \
pickle1.so pickle2.so pickle3.so \
noncopyable_export.so noncopyable_import.so \
ivect.so dvect.so
ivect.so dvect.so \
richcmp1.so richcmp2.so richcmp3.so
libboost_python.a: $(OBJ)
rm -f libboost_python.a
@@ -120,6 +122,15 @@ ivect.so: $(OBJ) ivect.o
dvect.so: $(OBJ) dvect.o
$(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so
richcmp1.so: $(OBJ) richcmp1.o
$(LD) $(LDOPTS) $(OBJ) richcmp1.o -o richcmp1.so
richcmp2.so: $(OBJ) richcmp2.o
$(LD) $(LDOPTS) $(OBJ) richcmp2.o -o richcmp2.so
richcmp3.so: $(OBJ) richcmp3.o
$(LD) $(LDOPTS) $(OBJ) richcmp3.o -o richcmp3.so
.cpp.o:
$(CPP) $(CPPOPTS) -c $*.cpp
@@ -134,6 +145,9 @@ test:
$(PYEXE) test_pickle2.py
$(PYEXE) test_pickle3.py
$(PYEXE) test_cross_module.py
$(PYEXE) test_richcmp1.py
$(PYEXE) test_richcmp2.py
$(PYEXE) test_richcmp3.py
clean:
rm -f $(OBJ) libboost_python.a libboost_python.a.input
@@ -150,6 +164,9 @@ clean:
rm -f noncopyable_import.o noncopyable_import.so
rm -f ivect.o ivect.so
rm -f dvect.o dvect.so
rm -f richcmp1.o richcmp1.so
rm -f richcmp2.o richcmp2.so
rm -f richcmp3.o richcmp3.so
rm -f so_locations *.pyc
rm -rf cxx_repository

View File

@@ -17,6 +17,9 @@ BOOST_UNIX=$(HOME)/boost
PYEXE="C:\Program files\Python\python.exe"
PYINC=/I"C:\Program files\Python\include"
PYLIB="C:\Program files\Python\libs\python15.lib"
#PYEXE="C:\Python21\python.exe"
#PYINC=/I"C:\Python21\include"
#PYLIB="C:\Python21\libs\python21.lib"
STDOPTS=/nologo /MD /GR /GX /Zm200
WARNOPTS=
@@ -43,7 +46,8 @@ all: boost_python.lib \
do_it_yourself_converters.pyd \
pickle1.pyd pickle2.pyd pickle3.pyd \
noncopyable_export.pyd noncopyable_import.pyd \
ivect.pyd dvect.pyd
ivect.pyd dvect.pyd \
richcmp1.pyd richcmp2.pyd richcmp3.pyd
boost_python.lib: $(OBJ)
$(LD) -lib /nologo /out:boost_python.lib $(OBJ)
@@ -87,6 +91,15 @@ ivect.pyd: $(OBJ) ivect.obj
dvect.pyd: $(OBJ) dvect.obj
$(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd"
richcmp1.pyd: $(OBJ) richcmp1.obj
$(LD) $(LDOPTS) $(OBJ) richcmp1.obj $(PYLIB) /export:initrichcmp1 /out:"richcmp1.pyd"
richcmp2.pyd: $(OBJ) richcmp2.obj
$(LD) $(LDOPTS) $(OBJ) richcmp2.obj $(PYLIB) /export:initrichcmp2 /out:"richcmp2.pyd"
richcmp3.pyd: $(OBJ) richcmp3.obj
$(LD) $(LDOPTS) $(OBJ) richcmp3.obj $(PYLIB) /export:initrichcmp3 /out:"richcmp3.pyd"
.cpp.obj:
$(CPP) $(CPPOPTS) /c $*.cpp
@@ -101,14 +114,17 @@ test:
$(PYEXE) test_pickle2.py
$(PYEXE) test_pickle3.py
$(PYEXE) test_cross_module.py --broken-auto-ptr
$(PYEXE) test_richcmp1.py
$(PYEXE) test_richcmp2.py
$(PYEXE) test_richcmp3.py
clean:
del *.obj
del *.lib
del *.exp
del *.idb
del *.pyd
del *.pyc
-del *.obj
-del *.lib
-del *.exp
-del *.idb
-del *.pyd
-del *.pyc
softlinks:
python $(BOOST_UNIX)/libs/python/build/filemgr.py $(BOOST_UNIX) softlinks

View File

@@ -112,10 +112,10 @@ that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
<h2>ILU</h2>
<p>
<a
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual">ILU</a>
href="ftp://ftp.parc.xerox.com/pub/ilu/ilu.html">ILU</a>
is a very ambitious project which tries to describe a module's interface
(types and functions) in terms of an <a
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual/manual_2.html">Interface
href="ftp://ftp.parc.xerox.com/pub/ilu/2.0b1/manual-html/manual_2.html">Interface
Specification Language</a> (ISL) so that it can be uniformly interfaced
to a wide range of computer languages, including Common Lisp, C++, C,
Modula-3, and Python. ILU can parse the ISL to generate a C++ language

View File

@@ -91,8 +91,8 @@ initialization. These bind the corresponding enum values to the appropriate
names so they can be used from Python:
<blockquote><pre>
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
mymodule.add(boost::python::make_ref(enum_value_1), "enum_value_1");
mymodule.add(boost::python::make_ref(enum_value_2), "enum_value_2");
...
</pre></blockquote>

View File

@@ -85,7 +85,7 @@ code before the last Python reference to it disappears:
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
PyObject* to_python(Foo* p)
{
return boost::python::python_extension_class_converters&ltFoo&gt::ptr_to_python(p);
return boost::python::python_extension_class_converters&lt;Foo&gt;::smart_ptr_to_python(p);
}
PyObject* to_python(const Foo* p)

106
doc/richcmp.html Normal file
View File

@@ -0,0 +1,106 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>Rich Comparisons</title>
<div>
<img src="../../../c++boost.gif"
alt="c++boost.gif (8819 bytes)"
align="center"
width="277" height="86">
<hr>
<h1>Rich Comparisons</h1>
<hr>
In Python versions up to and including Python 2.0, support for
implementing comparisons on user-defined classes and extension types
was quite simple. Classes could implement a <tt>__cmp__</tt> method
that was given two instances of a class as arguments, and could only
return <tt>0</tt> if they were equal or <tt>+1</tt> or <tt>-1</tt> if
they were not. The method could not raise an exception or return
anything other than an integer value.
In Python 2.1, <b>Rich Comparisons</b> were added (see
<a href="http://python.sourceforge.net/peps/pep-0207.html">PEP 207</a>).
Python classes can now individually overload each of the &lt;, &lt;=,
&gt;, &gt;=, ==, and != operations.
<p>
For more detailed information, search for "rich comparison"
<a href="http://www.python.org/doc/current/ref/customization.html"
>here</a>.
<p>
Boost.Python supports both automatic overloading and manual overloading
of the Rich Comparison operators. The <b>compile-time</b> support is
independent of the Python version that is used when compiling
Boost.Python extension modules. That is, <tt>op_lt</tt> for example can
always be used, and the C++ <tt>operator&lt;</tt> will always be bound
to the Python method <tt>__lt__</tt>. However, the <b>run-time</b>
behavior will depend on the Python version.
<p>
With Python versions before 2.1, the Rich Comparison operators will not
be called by Python when any of the six comparison operators
(<tt>&lt;</tt>, <tt>&lt;=</tt>, <tt>==</tt>, <tt>!=</tt>,
<tt>&gt;</tt>, <tt>&gt;=</tt>) is used in an expression. The only way
to access the corresponding methods is to call them explicitly, e.g.
<tt>a.__lt__(b)</tt>. Only with Python versions 2.1 or higher will
expressions like <tt>a &lt; b</tt> work as expected.
<p>
To support Rich Comparisions, the Python C API was modified between
Python versions 2.0 and 2.1. A new slot was introduced in the
<tt>PyTypeObject</tt> structure: <tt>tp_richcompare</tt>. For backwards
compatibility, a flag (<tt>Py_TPFLAGS_HAVE_RICHCOMPARE</tt>) has to be
set to signal to the Python interpreter that Rich Comparisions are
supported by a particular type.
There is only one flag for all the six comparison operators.
When any of the six operators is wrapped automatically or
manually, Boost.Python will set this flag. Attempts to use comparison
operators at the Python level that are not defined at the C++ level
will then lead to an <tt>AttributeError</tt> when the Python 2.1
(or higher) interpreter tries, e.g., <tt>a.__lt__(b)</tt>. That
is, in general all six operators should be supplied. Automatically
wrapped operators and manually wrapped operators can be mixed. For
example:<pre>
boost::python::class_builder&lt;code&gt; py_code(this_module, "code");
py_code.def(boost::python::constructor&lt;&gt;());
py_code.def(boost::python::constructor&lt;int&gt;());
py_code.def(boost::python::operators&lt;( boost::python::op_eq
| boost::python::op_ne)&gt;());
py_code.def(NotImplemented, "__lt__");
py_code.def(NotImplemented, "__le__");
py_code.def(NotImplemented, "__gt__");
py_code.def(NotImplemented, "__ge__");
</pre>
<tt>NotImplemented</tt> is a simple free function that (currently) has
to be provided by the user. For example:<pre>
boost::python::ref
NotImplemented(const code&amp;, const code&amp;) {
return
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
}
</pre>
See also:
<ul>
<li><a href="../example/richcmp1.cpp"><tt>../example/richcmp1.cpp</tt></a>
<li><a href="../example/richcmp2.cpp"><tt>../example/richcmp2.cpp</tt></a>
<li><a href="../example/richcmp3.cpp"><tt>../example/richcmp3.cpp</tt></a>
</ul>
<hr>
&copy; Copyright Nicholas K. Sauter &amp; Ralf W. Grosse-Kunstleve 2001.
Permission to copy, use, modify, sell and distribute this document is
granted provided this copyright notice appears in all copies. This
document is provided "as is" without express or implied warranty, and
with no claim as to its suitability for any purpose.
<p>
Updated: July 2001
</div>

View File

@@ -60,13 +60,27 @@
<b><tt class='method'>__str__</tt></b>(<i>self</i>)
<dd>
Create a string representation which is suitable for printing.
<dt>
<b><tt class='method'>__lt__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__le__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__eq__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__ne__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__gt__</tt></b>(<i>self, other</i>)
<dt>
<b><tt class='method'>__ge__</tt></b>(<i>self, other</i>)
<dd>
Rich Comparison methods.
New in Python 2.1.
See <a href="richcmp.html">Rich Comparisons</a>.
<dt>
<b><tt class='method'>__cmp__</tt></b>(<i>self, other</i>)
<dd>
Three-way compare function, used to implement comparison operators
(&lt; etc.) Should return a negative integer if <code> self < other
</code> , zero if <code> self == other </code> , a positive integer if
<code> self > other </code>.
Three-way compare function.
See <a href="richcmp.html">Rich Comparisons</a>.
<dt>
<b><tt class='method'>__hash__</tt></b>(<i>self</i>)
<dd>
@@ -544,17 +558,42 @@ Note that "__rrpow__" is an extension not present in plain Python.
<code>__cmp__, __rcmp__</code>
<td>
<code>cmp(left, right)</code><br>
<code>left &lt; right</code><br>
<code>left &lt;= right</code><br>
<code>left &gt; right</code><br>
<code>left &gt;= right</code><br>
<code>left == right</code><br>
<code>left != right</code>
<br>See <a href="richcmp.html">Rich Comparisons</a>.
<td>
<code>op_cmp</code>
<td>
<code>cpp_left &lt; cpp_right </code>
<br><code>cpp_right &lt; cpp_left</code>
<tr>
<td>
<code>__lt__</code>
<br><code>__le__</code>
<br><code>__eq__</code>
<br><code>__ne__</code>
<br><code>__gt__</code>
<br><code>__ge__</code>
<td>
<code>left &lt; right</code>
<br><code>left &lt;= right</code>
<br><code>left == right</code>
<br><code>left != right</code>
<br><code>left &gt; right</code>
<br><code>left &gt;= right</code>
<br>See <a href="richcmp.html">Rich Comparisons</a>
<td>
<code>op_lt</code>
<br><code>op_le</code>
<br><code>op_eq</code>
<br><code>op_ne</code>
<br><code>op_gt</code>
<br><code>op_ge</code>
<td>
<code>cpp_left &lt; cpp_right </code>
<br><code>cpp_left &lt;= cpp_right </code>
<br><code>cpp_left == cpp_right </code>
<br><code>cpp_left != cpp_right </code>
<br><code>cpp_left &gt; cpp_right </code>
<br><code>cpp_left &gt;= cpp_right </code>
<tr>
<td>

View File

@@ -36,7 +36,7 @@
template defines a whole raft of these conversions (for <code>T, T*,
T&amp;, std::auto_ptr&lt;T&gt;</code>, etc.), using the same inline
friend function technique employed by <a href=
"http://www.boost.org/libs/utility/operators.htm">the boost operators
"file:///c:/boost/site/libs/utility/operators.htm">the boost operators
library</a>.
<p>
Because the <code>to_python</code> and <code>from_python</code> functions

View File

@@ -20,6 +20,16 @@ namespace {
}
}
# ifdef BOOST_MSVC // fixes for JIT debugging
# include <windows.h>
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
= _set_se_translator(structured_exception_translator);
# endif
BOOST_PYTHON_MODULE_INIT(dvect)
{
try
@@ -43,3 +53,4 @@ BOOST_PYTHON_MODULE_INIT(dvect)
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -20,6 +20,16 @@ namespace {
}
}
# ifdef BOOST_MSVC // fixes for JIT debugging
# include <windows.h>
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
= _set_se_translator(structured_exception_translator);
# endif
BOOST_PYTHON_MODULE_INIT(ivect)
{
try
@@ -43,3 +53,4 @@ BOOST_PYTHON_MODULE_INIT(ivect)
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -6,6 +6,16 @@ namespace python = boost::python;
#include "noncopyable.h"
# ifdef BOOST_MSVC // fixes for JIT debugging
# include <windows.h>
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
= _set_se_translator(structured_exception_translator);
# endif
BOOST_PYTHON_MODULE_INIT(noncopyable_export)
{
try

View File

@@ -19,6 +19,16 @@ namespace { // Avoid cluttering the global namespace.
}
}
# ifdef BOOST_MSVC // fixes for JIT debugging
# include <windows.h>
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
extern "C" void (*old_translator)(unsigned int, EXCEPTION_POINTERS*)
= _set_se_translator(structured_exception_translator);
# endif
BOOST_PYTHON_MODULE_INIT(noncopyable_import)
{
try

View File

@@ -106,7 +106,7 @@ namespace {
{
if(args.size() != 1 || keywords.size() != 0) {
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
throw boost::python::argument_error();
throw boost::python::error_already_set();
}
const world& w = from_python(args[0].get(), type<const world&>());
ref mydict = getattr(args[0], "__dict__");
@@ -122,7 +122,7 @@ namespace {
{
if(args.size() != 2 || keywords.size() != 0) {
PyErr_SetString(PyExc_TypeError, "wrong number of arguments");
throw boost::python::argument_error();
throw boost::python::error_already_set();
}
world& w = from_python(args[0].get(), type<world&>());
ref mydict = getattr(args[0], "__dict__");

87
example/richcmp1.cpp Normal file
View File

@@ -0,0 +1,87 @@
// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter
// This example shows how to use rich comparisons for a vector type.
// It also shows how to template the entire wrapping of a std::vector.
// See vector_wrapper.h.
#include <boost/python/class_builder.hpp>
#include "vector_wrapper.h"
namespace vects {
struct dvect : public std::vector<double>
{
dvect() : std::vector<double>() {}
dvect(size_t n) : std::vector<double>(n) {}
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
{
std::vector<double>::iterator v_it = begin();
for (std::size_t i = 0; i < tuple.size(); i++)
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
boost::python::type<double>());
}
boost::python::tuple as_tuple() const
{
boost::python::tuple t(size());
for (std::size_t i = 0; i < size(); i++)
t.set_item(i,
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
return t;
}
# define DVECT_BINARY_OPERATORS(oper) \
friend std::vector<bool> \
operator##oper(const dvect& lhs, const dvect& rhs) \
{ \
if (lhs.size() != rhs.size()) { \
PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \
throw boost::python::error_already_set(); \
} \
std::vector<bool> result(lhs.size()); \
for (std::size_t i=0; i<lhs.size(); i++) { \
result[i] = (lhs[i] ##oper rhs[i]); \
} \
return result; \
}
DVECT_BINARY_OPERATORS(<)
DVECT_BINARY_OPERATORS(<=)
DVECT_BINARY_OPERATORS(==)
DVECT_BINARY_OPERATORS(!=)
DVECT_BINARY_OPERATORS(>)
DVECT_BINARY_OPERATORS(>=)
# undef VECTOR_BINARY_OPERATORS
};
} // namespace <anonymous>
namespace {
void init_module(boost::python::module_builder& this_module)
{
(void) example::wrap_vector(this_module, "vector_of_bool", bool());
boost::python::class_builder<vects::dvect> py_dvect(this_module, "dvect");
py_dvect.def(boost::python::constructor<boost::python::tuple>());
py_dvect.def(&vects::dvect::as_tuple, "as_tuple");
const long
comp_operators = ( boost::python::op_lt | boost::python::op_le
| boost::python::op_eq | boost::python::op_ne
| boost::python::op_gt | boost::python::op_ge);
py_dvect.def(boost::python::operators<comp_operators>());
}
} // namespace <anonymous>
BOOST_PYTHON_MODULE_INIT(richcmp1)
{
try {
boost::python::module_builder this_module("richcmp1");
// The actual work is done in a separate function in order
// to suppress a bogus VC60 warning.
init_module(this_module);
}
catch (...) { boost::python::handle_exception(); }
}

65
example/richcmp2.cpp Normal file
View File

@@ -0,0 +1,65 @@
// Example by Ralf W. Grosse-Kunstleve
// This example shows how to use rich comparisons for a type that
// does not support all six operators (<, <=, ==, !=, >, >=).
// To keep the example simple, we are using a "code" type does
// not really require rich comparisons. __cmp__ would be sufficient.
// However, with a more complicated type the main point of this
// example would be in danger of getting lost.
#include <boost/python/class_builder.hpp>
namespace {
// suppose operator< and operator> are not meaningful for code
class code {
public:
code(int c = 0) : m_code(c) {}
inline friend bool operator==(const code& lhs, const code& rhs) {
return lhs.m_code == rhs.m_code;
}
inline friend bool operator!=(const code& lhs, const code& rhs) {
return lhs.m_code != rhs.m_code;
}
private:
int m_code;
};
#if PYTHON_API_VERSION >= 1010
boost::python::ref
NotImplemented(const code&, const code&) {
return
boost::python::ref(Py_NotImplemented, boost::python::ref::increment_count);
}
#endif
}
namespace {
void init_module(boost::python::module_builder& this_module)
{
boost::python::class_builder<code> py_code(this_module, "code");
py_code.def(boost::python::constructor<>());
py_code.def(boost::python::constructor<int>());
py_code.def(boost::python::operators<( boost::python::op_eq
| boost::python::op_ne)>());
#if PYTHON_API_VERSION >= 1010
py_code.def(NotImplemented, "__lt__");
py_code.def(NotImplemented, "__le__");
py_code.def(NotImplemented, "__gt__");
py_code.def(NotImplemented, "__ge__");
#endif
}
} // namespace <anonymous>
BOOST_PYTHON_MODULE_INIT(richcmp2)
{
try {
boost::python::module_builder this_module("richcmp2");
// The actual work is done in a separate function in order
// to suppress a bogus VC60 warning.
init_module(this_module);
}
catch (...) { boost::python::handle_exception(); }
}

178
example/richcmp3.cpp Normal file
View File

@@ -0,0 +1,178 @@
// Example by Ralf W. Grosse-Kunstleve & Nicholas K. Sauter.
// Comprehensive operator overloading for two vector types and scalars.
#include <boost/python/class_builder.hpp>
#include "vector_wrapper.h"
#include "dvect.h"
#include "ivect.h"
#define VECT_VECT_OPERATORS(result_type, vect_type1, oper, vect_type2) \
namespace vects { \
result_type \
operator##oper (const vect_type1& lhs, const vect_type2& rhs) { \
if (lhs.size() != rhs.size()) { \
PyErr_SetString(PyExc_ValueError, "vectors have different sizes"); \
throw boost::python::error_already_set(); \
} \
result_type result(lhs.size()); \
for (std::size_t i=0; i<lhs.size(); i++) { \
result[i] = (lhs[i] ##oper rhs[i]); \
} \
return result; \
} \
}
#define VECT_SCALAR_OPERATORS(result_type, vect_type, oper, scalar_type) \
namespace vects { \
result_type \
operator##oper (const vect_type& lhs, const scalar_type& rhs) { \
result_type result(lhs.size()); \
for (std::size_t i=0; i<lhs.size(); i++) { \
result[i] = (lhs[i] ##oper rhs ); \
} \
return result; \
} \
}
#define SCALAR_VECT_OPERATORS(result_type, scalar_type, oper, vect_type) \
namespace vects { \
result_type \
operator##oper (const scalar_type& lhs, const vect_type& rhs) { \
result_type result(rhs.size()); \
for (std::size_t i=0; i<rhs.size(); i++) { \
result[i] = (lhs ##oper rhs[i]); \
} \
return result; \
} \
}
#define MATH_VECT_VECT_OPERATORS(result_type, vect_type1, vect_type2) \
VECT_VECT_OPERATORS(result_type, vect_type1, +, vect_type2) \
VECT_VECT_OPERATORS(result_type, vect_type1, -, vect_type2) \
VECT_VECT_OPERATORS(result_type, vect_type1, *, vect_type2) \
VECT_VECT_OPERATORS(result_type, vect_type1, /, vect_type2)
#define COMP_VECT_VECT_OPERATORS(vect_type1, vect_type2) \
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, <, vect_type2) \
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, <=, vect_type2) \
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, ==, vect_type2) \
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, !=, vect_type2) \
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, >, vect_type2) \
VECT_VECT_OPERATORS(std::vector<bool>, vect_type1, >=, vect_type2)
#define MATH_VECT_SCALAR_OPERATORS(result_type, vect_type, scalar_type) \
VECT_SCALAR_OPERATORS(result_type, vect_type, +, scalar_type) \
VECT_SCALAR_OPERATORS(result_type, vect_type, -, scalar_type) \
VECT_SCALAR_OPERATORS(result_type, vect_type, *, scalar_type) \
VECT_SCALAR_OPERATORS(result_type, vect_type, /, scalar_type)
#define COMP_VECT_SCALAR_OPERATORS(vect_type, scalar_type) \
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, <, scalar_type) \
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, <=, scalar_type) \
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, ==, scalar_type) \
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, !=, scalar_type) \
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, >, scalar_type) \
VECT_SCALAR_OPERATORS(std::vector<bool>, vect_type, >=, scalar_type)
#define MATH_SCALAR_VECT_OPERATORS(result_type, scalar_type, vect_type) \
SCALAR_VECT_OPERATORS(result_type, scalar_type, +, vect_type) \
SCALAR_VECT_OPERATORS(result_type, scalar_type, -, vect_type) \
SCALAR_VECT_OPERATORS(result_type, scalar_type, *, vect_type) \
SCALAR_VECT_OPERATORS(result_type, scalar_type, /, vect_type)
MATH_VECT_VECT_OPERATORS(dvect, dvect, dvect)
COMP_VECT_VECT_OPERATORS( dvect, dvect)
MATH_VECT_SCALAR_OPERATORS(dvect, dvect, double)
COMP_VECT_SCALAR_OPERATORS( dvect, double)
MATH_SCALAR_VECT_OPERATORS(dvect, double, dvect)
// comparison operators not needed since Python uses reflection
MATH_VECT_VECT_OPERATORS(ivect, ivect, ivect)
COMP_VECT_VECT_OPERATORS( ivect, ivect)
MATH_VECT_SCALAR_OPERATORS(ivect, ivect, int)
COMP_VECT_SCALAR_OPERATORS( ivect, int)
MATH_SCALAR_VECT_OPERATORS(ivect, int, ivect)
// comparison operators not needed since Python uses reflection
MATH_VECT_VECT_OPERATORS(dvect, dvect, ivect)
COMP_VECT_VECT_OPERATORS( dvect, ivect)
MATH_VECT_VECT_OPERATORS(dvect, ivect, dvect)
COMP_VECT_VECT_OPERATORS( ivect, dvect)
#undef VECT_VECT_OPERATORS
#undef SCALAR_VECT_OPERATORS
#undef VECT_SCALAR_OPERATORS
#undef MATH_VECT_VECT_OPERATORS
#undef COMP_VECT_VECT_OPERATORS
#undef MATH_VECT_SCALAR_OPERATORS
#undef COMP_VECT_SCALAR_OPERATORS
#undef MATH_SCALAR_VECT_OPERATORS
namespace {
void init_module(boost::python::module_builder& this_module)
{
(void) example::wrap_vector(this_module, "vector_of_bool", bool());
const long
math_operators ( boost::python::op_mul | boost::python::op_add
| boost::python::op_div | boost::python::op_sub);
const long
comp_operators = ( boost::python::op_lt | boost::python::op_le
| boost::python::op_eq | boost::python::op_ne
| boost::python::op_gt | boost::python::op_ge);
boost::python::class_builder<vects::dvect>
dvect_class(this_module, "dvect");
boost::python::class_builder<vects::ivect>
ivect_class(this_module, "ivect");
dvect_class.def(boost::python::constructor<boost::python::tuple>());
dvect_class.def(&vects::dvect::as_tuple,"as_tuple");
dvect_class.def(boost::python::operators<math_operators>());
dvect_class.def(boost::python::operators<math_operators>(),
boost::python::right_operand<double>() );
dvect_class.def(boost::python::operators<math_operators>(),
boost::python::left_operand<double>() );
dvect_class.def(boost::python::operators<math_operators>(),
boost::python::right_operand<vects::ivect>() );
dvect_class.def(boost::python::operators<comp_operators>());
dvect_class.def(boost::python::operators<comp_operators>(),
boost::python::right_operand<double>() );
// left_operand not needed since Python uses reflection
dvect_class.def(boost::python::operators<comp_operators>(),
boost::python::right_operand<vects::ivect>() );
ivect_class.def(boost::python::constructor<boost::python::tuple>());
ivect_class.def(&vects::ivect::as_tuple,"as_tuple");
ivect_class.def(boost::python::operators<math_operators>());
ivect_class.def(boost::python::operators<math_operators>(),
boost::python::right_operand<int>() );
ivect_class.def(boost::python::operators<math_operators>(),
boost::python::left_operand<int>() );
ivect_class.def(boost::python::operators<math_operators>(),
boost::python::right_operand<vects::dvect>() );
ivect_class.def(boost::python::operators<comp_operators>());
ivect_class.def(boost::python::operators<comp_operators>(),
boost::python::right_operand<int>() );
// left_operand not needed since Python uses reflection
ivect_class.def(boost::python::operators<comp_operators>(),
boost::python::right_operand<vects::dvect>() );
}
} // namespace <anonymous>
BOOST_PYTHON_MODULE_INIT(richcmp3)
{
try {
boost::python::module_builder this_module("richcmp3");
// The actual work is done in a separate function in order
// to suppress a bogus VC60 warning.
init_module(this_module);
}
catch (...) { boost::python::handle_exception(); }
}

View File

@@ -49,7 +49,7 @@ namespace { // Avoid cluttering the global namespace.
void delitem(std::vector<double>& vd, std::size_t key) {
if (key >= vd.size()) raise_vector_IndexError();
std::vector<double>::iterator vditer = vd.begin();
vd.erase(&vditer[key]);
vd.erase(vditer + key);
}
// Convert vector_double to a regular Python tuple.

View File

@@ -17,7 +17,8 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_abstract
doctest.testmod(test_abstract)
return doctest.testmod(test_abstract)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -133,7 +133,8 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_cross_module
doctest.testmod(test_cross_module)
return doctest.testmod(test_cross_module)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -16,7 +16,8 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_do_it_yourself_converters
doctest.testmod(test_do_it_yourself_converters)
return doctest.testmod(test_do_it_yourself_converters)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -44,7 +44,8 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_example1
doctest.testmod(test_example1)
return doctest.testmod(test_example1)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -11,7 +11,8 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_getting_started1
doctest.testmod(test_getting_started1)
return doctest.testmod(test_getting_started1)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -23,7 +23,9 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_getting_started2
doctest.testmod(test_getting_started2)
return doctest.testmod(test_getting_started2)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -25,7 +25,9 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_pickle1
doctest.testmod(test_pickle1)
return doctest.testmod(test_pickle1)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -39,7 +39,9 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_pickle2
doctest.testmod(test_pickle2)
return doctest.testmod(test_pickle2)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -19,12 +19,12 @@ r'''>>> import pickle3
... wd.z = 3. * number
... pstr = pickle.dumps(wd)
... wl = pickle.loads(pstr)
... print wd.greet(), wd.get_secret_number(), wd.__dict__
... print wl.greet(), wl.get_secret_number(), wl.__dict__
Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'}
Hello from California! 24 {'z': 72.0, 'x': 48, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyy'}
Hello from California! 42 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'}
Hello from California! 0 {'z': 126.0, 'x': 84, 'y': 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'}
... print wd.greet(), wd.get_secret_number(), wd.x, wd.y, wd.z
... print wl.greet(), wl.get_secret_number(), wl.x, wl.y, wl.z
Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0
Hello from California! 24 48 yyyyyyyyyyyyyyyyyyyyyyyy 72.0
Hello from California! 42 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0
Hello from California! 0 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0
'''
def run(args = None):
@@ -32,7 +32,8 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_pickle3
doctest.testmod(test_pickle3)
return doctest.testmod(test_pickle3)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

40
example/test_richcmp1.py Normal file
View File

@@ -0,0 +1,40 @@
r'''>>> import richcmp1
>>> d1 = richcmp1.dvect((0, 1, 3, 3, 6, 7))
>>> d2 = richcmp1.dvect((1, 2, 3, 4, 5, 6))
>>> print d1.as_tuple()
(0.0, 1.0, 3.0, 3.0, 6.0, 7.0)
>>> print d2.as_tuple()
(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
>>> print (d1 < d2).as_tuple()
(1, 1, 0, 1, 0, 0)
>>> print (d1 <= d2).as_tuple()
(1, 1, 1, 1, 0, 0)
>>> print (d1 == d2).as_tuple()
(0, 0, 1, 0, 0, 0)
>>> print (d1 != d2).as_tuple()
(1, 1, 0, 1, 1, 1)
>>> print (d1 > d2).as_tuple()
(0, 0, 0, 0, 1, 1)
>>> print (d1 >= d2).as_tuple()
(0, 0, 1, 0, 1, 1)
>>> try: d1 == richcmp1.dvect((1, 2, 3, 4, 5))
... except ValueError, e: print str(e)
...
vectors have different sizes
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_richcmp1
return doctest.testmod(test_richcmp1)
if __name__ == '__main__':
import sys
if ( hasattr(sys, 'version_info')
and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1)
or sys.version_info[0] > 2)):
sys.exit(run()[0])
else:
print "Python version 2.1 or higher required. Test skipped."

41
example/test_richcmp2.py Normal file
View File

@@ -0,0 +1,41 @@
r'''>>> import richcmp2
>>> c1 = richcmp2.code(1)
>>> c2 = richcmp2.code(2)
>>> c3 = richcmp2.code(2)
>>> print c1 == c2
0
>>> print c1 != c2
1
>>> print c2 == c3
1
>>> print c2 != c3
0
>>> print c1 < c2
1
>>> print c1 <= c2
1
>>> print c1 == c2
0
>>> print c1 != c2
1
>>> print c1 > c2
0
>>> print c1 >= c2
0
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_richcmp1
return doctest.testmod(test_richcmp1)
if __name__ == '__main__':
import sys
if ( hasattr(sys, 'version_info')
and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1)
or sys.version_info[0] > 2)):
sys.exit(run()[0])
else:
print "Python version 2.1 or higher required. Test skipped."

77
example/test_richcmp3.py Normal file
View File

@@ -0,0 +1,77 @@
r'''>>> import richcmp3
>>>
>>> iv = richcmp3.ivect((1,2,3,4,5))
>>> print iv.as_tuple()
(1, 2, 3, 4, 5)
>>> dv = richcmp3.dvect((2,-2,3,8,-5))
>>> print dv.as_tuple()
(2.0, -2.0, 3.0, 8.0, -5.0)
>>>
>>> print (iv+dv).as_tuple()
(3.0, 0.0, 6.0, 12.0, 0.0)
>>> print (iv+3).as_tuple()
(4, 5, 6, 7, 8)
>>> print (3+iv).as_tuple()
(4, 5, 6, 7, 8)
>>>
>>> print "vect vs. vect Comparisons:"
vect vs. vect Comparisons:
>>> print (iv < dv).as_tuple()
(1, 0, 0, 1, 0)
>>> print (iv <= dv).as_tuple()
(1, 0, 1, 1, 0)
>>> print (iv == dv).as_tuple()
(0, 0, 1, 0, 0)
>>> print (iv != dv).as_tuple()
(1, 1, 0, 1, 1)
>>> print (iv > dv).as_tuple()
(0, 1, 0, 0, 1)
>>> print (iv >= dv).as_tuple()
(0, 1, 1, 0, 1)
>>>
>>> print "vect vs. scalar Comparisons:"
vect vs. scalar Comparisons:
>>> print (iv < 3).as_tuple()
(1, 1, 0, 0, 0)
>>> print (iv <= 3).as_tuple()
(1, 1, 1, 0, 0)
>>> print (iv == 3).as_tuple()
(0, 0, 1, 0, 0)
>>> print (iv != 3).as_tuple()
(1, 1, 0, 1, 1)
>>> print (iv > 3).as_tuple()
(0, 0, 0, 1, 1)
>>> print (iv >= 3).as_tuple()
(0, 0, 1, 1, 1)
>>>
>>> print "scalar vs. vect Comparisons:"
scalar vs. vect Comparisons:
>>> print (3 < iv).as_tuple()
(0, 0, 0, 1, 1)
>>> print (3 <= iv).as_tuple()
(0, 0, 1, 1, 1)
>>> print (3 == iv).as_tuple()
(0, 0, 1, 0, 0)
>>> print (3 != iv).as_tuple()
(1, 1, 0, 1, 1)
>>> print (3 > iv).as_tuple()
(1, 1, 0, 0, 0)
>>> print (3 >= iv).as_tuple()
(1, 1, 1, 0, 0)
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_richcmp3
return doctest.testmod(test_richcmp3)
if __name__ == '__main__':
import sys
if ( hasattr(sys, 'version_info')
and ( (sys.version_info[0] == 2 and sys.version_info[1] >= 1)
or sys.version_info[0] > 2)):
sys.exit(run()[0])
else:
print "Python version 2.1 or higher required. Test skipped."

View File

@@ -11,7 +11,9 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_rwgk1
doctest.testmod(test_rwgk1)
return doctest.testmod(test_rwgk1)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -34,7 +34,9 @@ def run(args = None):
import sys
sys.argv = args
import doctest, test_simple_vector
doctest.testmod(test_simple_vector)
return doctest.testmod(test_simple_vector)
if __name__ == '__main__':
run()
import sys
sys.exit(run()[0])

View File

@@ -87,12 +87,18 @@ if (__name__ == "__main__"):
import sys, string
broken_auto_ptr = 0
n = 1
if (len(sys.argv) > 1):
if (sys.argv[1] == "--broken-auto-ptr"):
broken_auto_ptr = 1
if (len(sys.argv) > 2):
n = string.atoi(sys.argv[2])
else:
n = string.atoi(sys.argv[1])
if len(sys.argv) > 1:
argv = []
for x in sys.argv:
if x != '--broken-auto-ptr':
argv.append(x)
broken_auto_ptr = argv != sys.argv
sys.argv = argv
if len(sys.argv) > 1:
n = string.atoi(sys.argv[1])
for i in xrange(n):
f(broken_auto_ptr)

View File

@@ -87,12 +87,18 @@ if (__name__ == "__main__"):
import sys, string
broken_auto_ptr = 0
n = 1
if (len(sys.argv) > 1):
if (sys.argv[1] == "--broken-auto-ptr"):
broken_auto_ptr = 1
if (len(sys.argv) > 2):
n = string.atoi(sys.argv[2])
else:
n = string.atoi(sys.argv[1])
if len(sys.argv) > 1:
argv = []
for x in sys.argv:
if x != '--broken-auto-ptr':
argv.append(x)
broken_auto_ptr = argv != sys.argv
sys.argv = argv
if len(sys.argv) > 1:
n = string.atoi(sys.argv[1])
for i in xrange(n):
f(broken_auto_ptr)

117
example/vector_wrapper.h Normal file
View File

@@ -0,0 +1,117 @@
// Based on wrapVector.hh by Mike Owen and Jeff Johnson.
// http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/spheral/src/src/BPLWraps/CXXWraps/
#ifndef BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H
#define BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H
#include <boost/python/class_builder.hpp>
namespace example {
// A wrapper is used to define additional constructors. This wrapper
// is templated on the template parameter for its corresponding vector.
template <typename T>
struct vector_wrapper: std::vector<T>
{
// Tell the compiler how to convert a base class object to
// this wrapper object.
vector_wrapper(PyObject*,
const std::vector<T>& vec):
std::vector<T>(vec) {}
vector_wrapper(PyObject* self):
std::vector<T>() {}
vector_wrapper(PyObject* self,
std::size_t n):
std::vector<T>(n) {}
vector_wrapper(PyObject* self,
boost::python::tuple tuple):
std::vector<T>(tuple.size())
{
std::vector<T>::iterator vec = begin();
for (std::size_t i = 0; i < tuple.size(); i++)
vec[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
boost::python::type<T>());
}
};
void raise_vector_IndexError() {
PyErr_SetString(PyExc_IndexError, "vector index out of range");
throw boost::python::error_already_set();
}
template <typename T>
struct vector_access
{
static
T
getitem(const std::vector<T>& vec,
std::size_t key)
{
if (key >= vec.size()) raise_vector_IndexError();
return vec[key];
}
static
void
setitem(std::vector<T>& vec,
std::size_t key,
const T &value)
{
if (key >= vec.size()) raise_vector_IndexError();
vec[key] = value;
}
static
void
delitem(std::vector<T>& vec,
std::size_t key)
{
if (key >= vec.size()) raise_vector_IndexError();
vec.erase(vec.begin() + key);
}
// Convert vector<T> to a regular Python tuple.
static
boost::python::tuple
as_tuple(const std::vector<T>& vec)
{
// Create a python type of size vec.size().
boost::python::tuple t(vec.size());
for (std::size_t i = 0; i < vec.size(); i++) {
t.set_item(i,
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python(vec[i])));
}
return t;
}
};
// This function will build a vector<T> and add it to the given
// module with the given name.
template <typename T>
boost::python::class_builder<std::vector<T>, vector_wrapper<T> >
wrap_vector(boost::python::module_builder& module,
const std::string& vector_name,
const T&)
{
// Add the vector<T> to the module.
boost::python::class_builder<std::vector<T>, vector_wrapper<T> >
py_vector(module, vector_name.c_str());
// Define constructors and methods for the vector<T>.
py_vector.def(boost::python::constructor<>());
py_vector.def(boost::python::constructor<std::size_t>());
py_vector.def(boost::python::constructor<boost::python::tuple>());
py_vector.def(&std::vector<T>::size, "__len__");
py_vector.def(&vector_access<T>::getitem, "__getitem__");
py_vector.def(&vector_access<T>::setitem, "__setitem__");
py_vector.def(&vector_access<T>::delitem, "__delitem__");
py_vector.def(&vector_access<T>::as_tuple, "as_tuple");
return py_vector;
}
}
#endif // BOOST_PYTHON_EXAMPLE_VECTOR_WRAPPER_H

View File

@@ -70,6 +70,14 @@ class instance
PyObject* oct();
PyObject* hex();
// Rich comparisons
PyObject* lt(PyObject* other);
PyObject* le(PyObject* other);
PyObject* eq(PyObject* other);
PyObject* ne(PyObject* other);
PyObject* gt(PyObject* other);
PyObject* ge(PyObject* other);
private: // noncopyable, without the size bloat
instance(const instance&);
void operator=(const instance&);
@@ -169,6 +177,14 @@ class class_t
PyObject* instance_number_float(PyObject*) const;
PyObject* instance_number_oct(PyObject*) const;
PyObject* instance_number_hex(PyObject*) const;
private: // Implement rich comparisons
PyObject* instance_lt(PyObject*, PyObject*) const;
PyObject* instance_le(PyObject*, PyObject*) const;
PyObject* instance_eq(PyObject*, PyObject*) const;
PyObject* instance_ne(PyObject*, PyObject*) const;
PyObject* instance_gt(PyObject*, PyObject*) const;
PyObject* instance_ge(PyObject*, PyObject*) const;
private: // Miscellaneous "special" methods
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const;
@@ -477,6 +493,42 @@ PyObject* class_t<T>::instance_number_hex(PyObject* obj) const
return downcast<T>(obj)->hex();
}
template <class T>
PyObject* class_t<T>::instance_lt(PyObject* obj, PyObject* other) const
{
return downcast<T>(obj)->lt(other);
}
template <class T>
PyObject* class_t<T>::instance_le(PyObject* obj, PyObject* other) const
{
return downcast<T>(obj)->le(other);
}
template <class T>
PyObject* class_t<T>::instance_eq(PyObject* obj, PyObject* other) const
{
return downcast<T>(obj)->eq(other);
}
template <class T>
PyObject* class_t<T>::instance_ne(PyObject* obj, PyObject* other) const
{
return downcast<T>(obj)->ne(other);
}
template <class T>
PyObject* class_t<T>::instance_gt(PyObject* obj, PyObject* other) const
{
return downcast<T>(obj)->gt(other);
}
template <class T>
PyObject* class_t<T>::instance_ge(PyObject* obj, PyObject* other) const
{
return downcast<T>(obj)->ge(other);
}
namespace detail {
inline dictionary& class_base::dict()
{

View File

@@ -39,7 +39,7 @@ typedef base_object<PyTypeObject> python_type;
//
// class_t template member function implementations
// base_object member function implementations
//
template <class python_type>
base_object<python_type>::base_object(PyTypeObject* type_obj)

View File

@@ -57,7 +57,7 @@
# define BOOST_CSTD_ std
# endif
#ifdef _WIN32
#if defined(_WIN32) || defined(__CYGWIN__)
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" __declspec(dllexport) void init##name()
#else
# define BOOST_PYTHON_MODULE_INIT(name) extern "C" void init##name()

View File

@@ -616,6 +616,12 @@ class extension_class
choose_op<(which & op_and)>::template args<Operand>::add(this);
choose_op<(which & op_xor)>::template args<Operand>::add(this);
choose_op<(which & op_or)>::template args<Operand>::add(this);
choose_op<(which & op_gt)>::template args<Operand>::add(this);
choose_op<(which & op_ge)>::template args<Operand>::add(this);
choose_op<(which & op_lt)>::template args<Operand>::add(this);
choose_op<(which & op_le)>::template args<Operand>::add(this);
choose_op<(which & op_eq)>::template args<Operand>::add(this);
choose_op<(which & op_ne)>::template args<Operand>::add(this);
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
@@ -645,6 +651,12 @@ class extension_class
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
choose_op<(which & op_ne)>::template args<Left,Right>::add(this);
}
template <long which, class Left, class Right>

View File

@@ -73,7 +73,8 @@ namespace detail {
struct parameter_traits
{
private:
typedef const_ref_selector<boost::is_reference<T>::value> selector;
enum { is_ref = boost::is_reference<T>::value };
typedef const_ref_selector<is_ref> selector;
public:
typedef typename selector::template const_ref<T>::type const_reference;
};

View File

@@ -45,7 +45,7 @@ class type_object_base : public python_type
public:
enum capability {
hash, call, str, getattr, setattr, compare, repr,
hash, call, str, getattr, setattr, compare, repr, richcompare,
mapping_length, mapping_subscript, mapping_ass_subscript,
@@ -115,6 +115,14 @@ class type_object_base : public python_type
virtual PyObject* instance_number_float(PyObject*) const;
virtual PyObject* instance_number_oct(PyObject*) const;
virtual PyObject* instance_number_hex(PyObject*) const;
public: // Callbacks for rich comparisons
virtual PyObject* instance_lt(PyObject*, PyObject*) const;
virtual PyObject* instance_le(PyObject*, PyObject*) const;
virtual PyObject* instance_eq(PyObject*, PyObject*) const;
virtual PyObject* instance_ne(PyObject*, PyObject*) const;
virtual PyObject* instance_gt(PyObject*, PyObject*) const;
virtual PyObject* instance_ge(PyObject*, PyObject*) const;
};
template <class T>
@@ -375,8 +383,12 @@ PyObject* reprable<Base>::instance_repr(PyObject* obj) const
// This macro gets the length of an array as a compile-time constant, and will
// fail to compile if the parameter is a pointer.
#ifdef __BORLANDC__ // smart implementation doesn't work for borland; maybe someone knows a workaround?
# define PY_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
#else
# define PY_ARRAY_LENGTH(a) \
(sizeof(::boost::python::detail::countof_validate(a, &(a))) ? sizeof(a) / sizeof((a)[0]) : 0)
#endif
template<typename T>
inline void countof_validate(T* const, T* const*);

View File

@@ -65,7 +65,13 @@ enum operator_id
op_long = 0x20000,
op_float = 0x40000,
op_str = 0x80000,
op_cmp = 0x100000
op_cmp = 0x100000,
op_gt = 0x200000,
op_ge = 0x400000,
op_lt = 0x800000,
op_le = 0x1000000,
op_eq = 0x2000000,
op_ne = 0x4000000
};
// Wrap the operators given by "which". Usage:
@@ -301,6 +307,12 @@ namespace detail
PY_DEFINE_BINARY_OPERATORS(and, &);
PY_DEFINE_BINARY_OPERATORS(xor, ^);
PY_DEFINE_BINARY_OPERATORS(or, |);
PY_DEFINE_BINARY_OPERATORS(gt, >);
PY_DEFINE_BINARY_OPERATORS(ge, >=);
PY_DEFINE_BINARY_OPERATORS(lt, <);
PY_DEFINE_BINARY_OPERATORS(le, <=);
PY_DEFINE_BINARY_OPERATORS(eq, ==);
PY_DEFINE_BINARY_OPERATORS(ne, !=);
PY_DEFINE_UNARY_OPERATORS(neg, -);
PY_DEFINE_UNARY_OPERATORS(pos, +);

View File

@@ -203,7 +203,8 @@ namespace detail {
}
if (!BOOST_CSTD_::strcmp(name, "__reduce__"))
{
ref target(as_object(this), ref::increment_count);
PyObject* self = as_object(this);
ref target(self, ref::increment_count);
return bound_function::create(target, global_class_reduce());
}
@@ -735,6 +736,36 @@ PyObject* instance::hex()
return callback<PyObject*>::call_method(this, "__hex__");
}
PyObject* instance::lt(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__lt__", other);
}
PyObject* instance::le(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__le__", other);
}
PyObject* instance::eq(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__eq__", other);
}
PyObject* instance::ne(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__ne__", other);
}
PyObject* instance::gt(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__gt__", other);
}
PyObject* instance::ge(PyObject* other)
{
return callback<PyObject*>::call_method(this, "__ge__", other);
}
namespace {
struct named_capability
{
@@ -746,6 +777,12 @@ namespace {
{
{ "__hash__", detail::type_object_base::hash },
{ "__cmp__", detail::type_object_base::compare },
{ "__gt__", detail::type_object_base::richcompare },
{ "__ge__", detail::type_object_base::richcompare },
{ "__lt__", detail::type_object_base::richcompare },
{ "__le__", detail::type_object_base::richcompare },
{ "__eq__", detail::type_object_base::richcompare },
{ "__ne__", detail::type_object_base::richcompare },
{ "__repr__", detail::type_object_base::repr },
{ "__str__", detail::type_object_base::str },
{ "__call__", detail::type_object_base::call },
@@ -808,7 +845,7 @@ namespace detail {
// Enable the special handler for methods of the given name, if any.
void enable_named_method(boost::python::detail::class_base* type_obj, const char* name)
{
const std::size_t num_enablers = sizeof(enablers) / sizeof(enablers[0]);
const std::size_t num_enablers = PY_ARRAY_LENGTH(enablers);
// Make sure this ends with "__" since we'll only compare the head of the
// string. This is done to make the __getattr__<name>__/__setattr__<name>__

View File

@@ -15,6 +15,7 @@ def gen_extclass(args):
// gen_extclass.python
// Revision History:
// 17 Apr 01 Comment added with reference to cross_module.hpp (R.W. Grosse-Kunstleve)
// 05 Mar 01 Fixed a bug which prevented auto_ptr values from being converted
// to_python (Dave Abrahams)
@@ -171,6 +172,14 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
// and U. T is the class the user really intends to wrap. U is a class derived
// from T with some virtual function overriding boilerplate, or if there are no
// virtual functions, U = held_instance<T>.
//
// A look-alike of this class in root/boost/python/cross_module.hpp
// is used for the implementation of the cross-module support
// (export_converters and import_converters). If from_python
// and to_python converters are added or removed from the class
// below, the class python_import_extension_class_converters has
// to be modified accordingly.
//
template <class T, class U = boost::python::detail::held_instance<T> >
class python_extension_class_converters
{
@@ -607,6 +616,12 @@ class extension_class
choose_op<(which & op_and)>::template args<Operand>::add(this);
choose_op<(which & op_xor)>::template args<Operand>::add(this);
choose_op<(which & op_or)>::template args<Operand>::add(this);
choose_op<(which & op_gt)>::template args<Operand>::add(this);
choose_op<(which & op_ge)>::template args<Operand>::add(this);
choose_op<(which & op_lt)>::template args<Operand>::add(this);
choose_op<(which & op_le)>::template args<Operand>::add(this);
choose_op<(which & op_eq)>::template args<Operand>::add(this);
choose_op<(which & op_ne)>::template args<Operand>::add(this);
choose_unary_op<(which & op_neg)>::template args<Operand>::add(this);
choose_unary_op<(which & op_pos)>::template args<Operand>::add(this);
choose_unary_op<(which & op_abs)>::template args<Operand>::add(this);
@@ -636,6 +651,12 @@ class extension_class
choose_op<(which & op_xor)>::template args<Left,Right>::add(this);
choose_op<(which & op_or)>::template args<Left,Right>::add(this);
choose_op<(which & op_cmp)>::template args<Left,Right>::add(this);
choose_op<(which & op_gt)>::template args<Left,Right>::add(this);
choose_op<(which & op_ge)>::template args<Left,Right>::add(this);
choose_op<(which & op_lt)>::template args<Left,Right>::add(this);
choose_op<(which & op_le)>::template args<Left,Right>::add(this);
choose_op<(which & op_eq)>::template args<Left,Right>::add(this);
choose_op<(which & op_ne)>::template args<Left,Right>::add(this);
}
template <long which, class Left, class Right>

View File

@@ -79,7 +79,8 @@ namespace detail {
struct parameter_traits
{
private:
typedef const_ref_selector<boost::is_reference<T>::value> selector;
enum { is_ref = boost::is_reference<T>::value };
typedef const_ref_selector<is_ref> selector;
public:
typedef typename selector::template const_ref<T>::type const_reference;
};

View File

@@ -159,6 +159,28 @@ static PyObject* do_instance_repr(PyObject* obj)
return call(obj, &type_object_base::instance_repr);
}
static PyObject* do_instance_richcompare(PyObject* obj, PyObject* other, int d)
{
#if PYTHON_API_VERSION >= 1010
switch(d)
{
case Py_LT:
return call(obj, &type_object_base::instance_lt, other);
case Py_LE:
return call(obj, &type_object_base::instance_le, other);
case Py_EQ:
return call(obj, &type_object_base::instance_eq, other);
case Py_NE:
return call(obj, &type_object_base::instance_ne, other);
case Py_GT:
return call(obj, &type_object_base::instance_gt, other);
case Py_GE:
return call(obj, &type_object_base::instance_ge, other);
}
#endif
return 0;
}
static int do_instance_compare(PyObject* obj, PyObject* other)
{
return call(obj, &type_object_base::instance_compare, other);
@@ -406,7 +428,7 @@ namespace
bool add_capability_general(type_object_base::capability capability, PyTypeObject* dest)
{
assert(dest != 0);
switch(capability)
{
ENABLE_GENERAL_CAPABILITY(hash);
@@ -435,6 +457,20 @@ void create_method_table_if_null(T*& table)
}
}
bool add_capability_richcompare(type_object_base::capability capability, PyTypeObject* dest)
{
assert(dest != 0);
if (capability == type_object_base::richcompare) {
#if PYTHON_API_VERSION >= 1010
dest->tp_richcompare = &do_instance_richcompare;
dest->tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
#endif
return true;
}
return false;
}
#define ENABLE_MAPPING_CAPABILITY(field) \
case type_object_base::mapping_##field: \
create_method_table_if_null(dest); \
@@ -548,6 +584,8 @@ namespace detail {
{
if(add_capability_general(capability, dest_))
return;
if(add_capability_richcompare(capability, dest_))
return;
if(add_capability_mapping(capability, dest_->tp_as_mapping))
return;
if(add_capability_sequence(capability, dest_->tp_as_sequence))
@@ -975,6 +1013,36 @@ PyObject* type_object_base::instance_number_hex(PyObject*) const
return unimplemented("instance_number_hex");
}
PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const
{
return unimplemented("instance_lt");
}
PyObject* type_object_base::instance_le(PyObject*, PyObject*) const
{
return unimplemented("instance_le");
}
PyObject* type_object_base::instance_eq(PyObject*, PyObject*) const
{
return unimplemented("instance_eq");
}
PyObject* type_object_base::instance_ne(PyObject*, PyObject*) const
{
return unimplemented("instance_ne");
}
PyObject* type_object_base::instance_gt(PyObject*, PyObject*) const
{
return unimplemented("instance_gt");
}
PyObject* type_object_base::instance_ge(PyObject*, PyObject*) const
{
return unimplemented("instance_ge");
}
}} // namespace boost::python
#ifdef TYPE_OBJECT_BASE_STANDALONE_TEST

View File

@@ -15,7 +15,9 @@
#include <math.h> // for pow()
#include <boost/rational.hpp>
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730
#if defined(__sgi) \
&& ( (defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730) \
&& !defined(__GNUC__))
inline double pow(int x, int y) { return pow(static_cast<double>(x), y); }
#endif

View File

@@ -19,10 +19,13 @@ Load up the extension module
Automatic checking of the number and type of arguments. Foo's constructor takes
a single long parameter.
>>> ext = Foo()
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: function requires exactly 1 argument; 0 given
>>> try:
... ext = Foo()
... except TypeError, err:
... assert re.match(r'function .* exactly 1 argument;? \(?0 given\)?',
... str(err))
... else:
... print 'no exception'
>>> try: ext = Foo('foo')
... except TypeError, err:
@@ -419,7 +422,7 @@ Some simple overloading tests:
>>> try: r = Range('yikes')
... except TypeError, e:
... assert re.match(
... 'No overloaded functions match [(]Range, string[)]\. Candidates are:\n.*\n.*',
... 'No overloaded functions match [(]Range, str[a-z]*[)]\. Candidates are:\n.*\n.*',
... str(e))
... else: print 'no exception'
@@ -629,7 +632,7 @@ Testing overloaded free functions
15
>>> try: overloaded(1, 'foo')
... except TypeError, err:
... assert re.match("No overloaded functions match \(int, string\)\. Candidates are:",
... assert re.match("No overloaded functions match \(int, str[a-z]*\)\. Candidates are:",
... str(err))
... else:
... print 'no exception'
@@ -659,7 +662,7 @@ Testing overloaded constructors
5
>>> try: over = OverloadTest(1, 'foo')
... except TypeError, err:
... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:",
... assert re.match("No overloaded functions match \(OverloadTest, int, str[a-z]*\)\. Candidates are:",
... str(err))
... else:
... print 'no exception'
@@ -681,7 +684,7 @@ Testing overloaded methods
5
>>> try: over.overloaded(1,'foo')
... except TypeError, err:
... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:",
... assert re.match("No overloaded functions match \(OverloadTest, int, str[a-z]*\)\. Candidates are:",
... str(err))
... else:
... print 'no exception'
@@ -1014,9 +1017,12 @@ test inheritB2
-2
>>> str(i)
'2'
>>> j = i/i
Traceback (innermost last):
TypeError: bad operand type(s) for /
>>> try: j = i/i
... except TypeError, err:
... assert re.match(r'(bad|unsupported) operand type\(s\) for /',
... str(err))
... else: print 'no exception'
>>> j = abs(i)
Traceback (innermost last):
TypeError: bad operand type for abs()
@@ -1188,7 +1194,7 @@ def run(args = None):
if args is not None:
sys.argv = args
import doctest, comprehensive
doctest.testmod(comprehensive)
return doctest.testmod(comprehensive)
if __name__ == '__main__':
run()
sys.exit(run()[0])