diff --git a/example/abstract.cpp b/example/abstract.cpp new file mode 100644 index 00000000..41d34def --- /dev/null +++ b/example/abstract.cpp @@ -0,0 +1,34 @@ +// Example by Ullrich Koethe +#include "boost/python/class_builder.hpp" +#include + +struct Abstract +{ + virtual std::string test() = 0; +}; + +struct Abstract_callback: Abstract +{ + Abstract_callback(PyObject * self) + : m_self(self) + {} + + std::string test() + { + return boost::python::callback::call_method(m_self, "test"); + } + + PyObject * m_self; +}; + +extern "C" +DL_EXPORT(void) +initabstract() +{ + boost::python::module_builder a("abstract"); + + boost::python::class_builder + a_class(a, "Abstract"); + a_class.def(boost::python::constructor<>()); // wrap a constructor + a_class.def(&Abstract::test, "test"); +} diff --git a/example/dvect.cpp b/example/dvect.cpp new file mode 100644 index 00000000..3228010c --- /dev/null +++ b/example/dvect.cpp @@ -0,0 +1,69 @@ +#include "ivect.h" +#include "dvect.h" +#include +#include +namespace python = boost::python; + +namespace { + + vects::ivect dvect_as_ivect(const vects::dvect& dv) + { + vects::ivect iv(dv.size()); + vects::ivect::iterator iviter = iv.begin(); + for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast(dv[i]); + return iv; + } + + boost::python::tuple ivect_as_tuple(const vects::ivect& iv) + { + return iv.as_tuple(); + } + + std::auto_ptr auto_ptr_ivect(const vects::dvect& dv) + { + return std::auto_ptr(new vects::ivect(dvect_as_ivect(dv))); + } + + boost::shared_ptr shared_ptr_ivect(const vects::dvect& dv) + { + return boost::shared_ptr(new vects::ivect(dvect_as_ivect(dv))); + } + + boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr& iv) + { + return iv->as_tuple(); + } + + boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr& iv) + { + return iv->as_tuple(); + } +} + +extern "C" +DL_EXPORT(void) +initdvect() +{ + try + { + python::module_builder this_module("dvect"); + + python::x_class_builder dvect_class(this_module, "dvect"); + + python::import_class_builder ivect_class("ivect", "ivect"); + + dvect_class.def(python::constructor()); + dvect_class.def(&vects::dvect::as_tuple, "as_tuple"); + dvect_class.def(dvect_as_ivect, "as_ivect"); + + this_module.def(ivect_as_tuple, "ivect_as_tuple"); + dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect"); + dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect"); + this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple"); + this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/dvect.h b/example/dvect.h new file mode 100644 index 00000000..8ffe7b50 --- /dev/null +++ b/example/dvect.h @@ -0,0 +1,32 @@ +#ifndef DVECT_H +#define DVECT_H + +#include +#include + +namespace vects { + + struct dvect : public std::vector + { + dvect() : std::vector() {} + dvect(size_t n) : std::vector(n) {} + dvect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (int i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (int i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + }; +} + +#endif // DVECT_H diff --git a/example/example1.cpp b/example/example1.cpp deleted file mode 100644 index 467ac0dc..00000000 --- a/example/example1.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include - -namespace hello { - class world - { - public: - world(int) {} - ~world() {} - const char* get() const { return "hi, world"; } - }; - - size_t length(const world& x) { return strlen(x.get()); } -} - -#include - -// Python requires an exported function called init in every -// extension module. This is where we build the module contents. -extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void inithello() -{ - try - { - // create an object representing this extension module - boost::python::module_builder hello("hello"); - - // Create the Python type object for our extension class - boost::python::class_builder world_class(hello, "world"); - - // Add the __init__ function - world_class.def(boost::python::constructor()); - // Add a regular member function - world_class.def(&hello::world::get, "get"); - - // Add a regular function to the module - hello.def(hello::length, "length"); - } - catch(...) - { - boost::python::handle_exception(); // Deal with the exception for Python - } -} - -// Win32 DLL boilerplate -#if defined(_WIN32) -#include -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) -{ - return 1; -} -#endif // _WIN32 diff --git a/example/rwgk1.cpp b/example/getting_started1.cpp similarity index 74% rename from example/rwgk1.cpp rename to example/getting_started1.cpp index b21ae4d1..9679a2a4 100644 --- a/example/rwgk1.cpp +++ b/example/getting_started1.cpp @@ -8,21 +8,18 @@ namespace { // Avoid cluttering the global namespace. } #include - namespace python = boost::python; // Python requires an exported function called init in every // extension module. This is where we build the module contents. extern "C" -#ifdef _WIN32 -__declspec(dllexport) -#endif -void initrwgk1() +DL_EXPORT(void) +initgetting_started1() { try { // Create an object representing this extension module. - python::module_builder this_module("rwgk1"); + python::module_builder this_module("getting_started1"); // Add regular functions to the module. this_module.def(greet, "greet"); @@ -33,9 +30,3 @@ void initrwgk1() python::handle_exception(); // Deal with the exception for Python } } - -// Win32 DLL boilerplate -#if defined(_WIN32) -#include -extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; } -#endif // _WIN32 diff --git a/example/getting_started2.cpp b/example/getting_started2.cpp new file mode 100644 index 00000000..82b4a6df --- /dev/null +++ b/example/getting_started2.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + public: + world(const std::string& country) { this->country = country; } + std::string greet() const { return "Hello from " + country + "!"; } + }; + + // A function taking a world object as an argument. + std::string invite(const world& w) { + return w.greet() + " Please come soon!"; + } +} + +extern "C" +DL_EXPORT(void) +initgetting_started2() +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("getting_started2"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + + // Add invite() as a regular function to the module. + this_module.def(invite, "invite"); + + // Even better, invite() can also be made a member of world_class!!! + world_class.def(invite, "invite"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/getting_started3.cpp b/example/getting_started3.cpp new file mode 100644 index 00000000..7e827249 --- /dev/null +++ b/example/getting_started3.cpp @@ -0,0 +1,122 @@ +/* + This example shows how to make an Extension Class "pickleable". + + Python's pickle module implements a basic but powerful algorithm + for "pickling" (a.k.a. serializing, marshalling or flattening) + nearly arbitrary Python objects. + + The user can influence how an Extension Class instance is pickled + by defining three special methods: __getinitargs__(), + __getstate__(), and __setstate(). This interface is similar to + that for regular Python classes as described in detail in the + Python Library Reference for pickle: + + http://www.python.org/doc/current/lib/module-pickle.html + + When an Extension Class instance is pickled, __getinitargs__() is + called, if implemented. This method should return a tuple + containing the arguments to be passed to the class constructor when + the object is restored. + + If there is no __getstate__() method, the instance's __dict__ is + pickled if it is not empty. If __getstate__() is defined, it should + return an object representing the state of the instance. + + If there is no __setstate__() method, __getstate__() must return a + dictionary. When the instance is restored, the items in this dictionary + are added to the instance's __dict__. + + If the Extension Class defines __setstate__(), the pickle loader + calls it with the result of __getstate__() as arguments. In this + case, the state object need not be a dictionary. The + __getstate__() and __setstate__() methods can do what they want. + + If both __getinitargs__() and __getstate__() are defined, the + instance is restored by first calling the constructor with + the result of __getinitargs__() as argument. After the instance + is reconstructed, the __dict__ is updated or __setstate__() is + called if implemented. + + The mechanism described here is an exact replication of that one + implemented by Jim Fulton's ExtensionClass (included in Zope 2.2.2). + */ + +#include +#include + +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class world + { + private: + std::string country; + int secret_number; + public: + world(const std::string& country) : secret_number(0) { + this->country = country; + } + std::string greet() const { return "Hello from " + country + "!"; } + std::string get_country() const { return country; } + void set_secret_number(int number) { secret_number = number; } + int get_secret_number() const { return secret_number; } + }; + + // Support for pickle. + python::tuple world_getinitargs(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_country()); + return result; + } + + python::tuple world_getstate(const world& w) { + python::tuple result(1); + result.set_item(0, w.get_secret_number()); + return result; + } + + void world_setstate(world& w, python::tuple state) { + if (state.size() != 1) { + PyErr_SetString(PyExc_ValueError, + "Unexpected argument in call to __setstate__."); + throw python::error_already_set(); + } + int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(), + python::type()); + if (number != 42) + w.set_secret_number(number); + } +} + +extern "C" +DL_EXPORT(void) +initgetting_started3() +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("getting_started3"); + + // Create the Python type object for our extension class. + python::class_builder world_class(this_module, "world"); + + // Add the __init__ function. + world_class.def(python::constructor()); + // Add a regular member function. + world_class.def(&world::greet, "greet"); + world_class.def(&world::get_secret_number, "get_secret_number"); + world_class.def(&world::set_secret_number, "set_secret_number"); + + // Support for pickle. + world_class.def(world_getinitargs, "__getinitargs__"); + world_class.def(world_getstate, "__getstate__"); + world_class.def(world_setstate, "__setstate__"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/getting_started4.cpp b/example/getting_started4.cpp new file mode 100644 index 00000000..0c7bd7ee --- /dev/null +++ b/example/getting_started4.cpp @@ -0,0 +1,104 @@ +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // A wrapper is used to define additional constructors. + // + struct vector_double_wrapper: std::vector + { + // Tell the compiler how to convert a base class object to + // this wrapper object. + vector_double_wrapper(PyObject*, const std::vector& vd) + : std::vector(vd) {} + + vector_double_wrapper(PyObject* self) + : std::vector() {} + + vector_double_wrapper(PyObject* self, const int n) + : std::vector(n) {} + + vector_double_wrapper(PyObject* self, python::tuple tuple) + : std::vector(tuple.size()) + { + std::vector::iterator vd = begin(); + for (int i = 0; i < tuple.size(); i++) + vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + python::type()); + } + }; + + double getitem(const std::vector& vd, const std::size_t key) { + return vd[key]; + } + + void setitem(std::vector& vd, const std::size_t key, + const double &d) { + std::vector::iterator vditer = vd.begin(); + vditer[key] = d; + } + + void delitem(std::vector& vd, const std::size_t key) { + std::vector::iterator vditer = vd.begin(); + vd.erase(&vditer[key]); + } + + // Convert vector_double to a regular Python tuple. + // + python::tuple as_tuple(const std::vector& vd) + { + python::tuple t(vd.size()); + for (int i = 0; i < vd.size(); i++) t.set_item(i, + python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i]))); + return t; + } + + // Function returning a vector_double object to Python. + // + std::vector foo(const int n) + { + std::vector vd(n); + std::vector::iterator vditer = vd.begin(); + for (int i = 0; i < n; i++) vditer[i] = double(i); + return vd; + } + + // Same as foo(), but avoid copying on return. + // + std::auto_ptr > bar(const int n) + { + std::auto_ptr > vdptr(new std::vector(n)); + std::vector::iterator vditer = vdptr->begin(); + for (int i = 0; i < n; i++) vditer[i] = double(10 * i); + return vdptr; + } +} + +extern "C" +DL_EXPORT(void) +initgetting_started4() +{ + try + { + python::module_builder this_module("getting_started4"); + + python::class_builder, vector_double_wrapper> + vector_double(this_module, "vector_double"); + + vector_double.def(python::constructor<>()); + vector_double.def(python::constructor()); + vector_double.def(python::constructor()); + vector_double.def(&std::vector::size, "__len__"); + vector_double.def(getitem, "__getitem__"); + vector_double.def(setitem, "__setitem__"); + vector_double.def(delitem, "__delitem__"); + vector_double.def(as_tuple, "as_tuple"); + + this_module.def(foo, "foo"); + this_module.def(bar, "bar"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/getting_started5.cpp b/example/getting_started5.cpp new file mode 100644 index 00000000..e82fec30 --- /dev/null +++ b/example/getting_started5.cpp @@ -0,0 +1,127 @@ +/* + This example shows how to convert a class from and to native + Python objects, such as tuples. + + We do not want to expose the helper class MillerIndex as an + Extension Class. However, in order to simplify the wrapper code, + we want to define from_python() and to_python() functions for + class MillerIndex. + + Consider the alternatives: + + - Expose MillerIndex as an Extension Class. + We need a constructor MillerIndex(python::tuple). + Python function calls become more complex: + foo(MillerIndex((1,2,3)) instead of foo((1,2,3)) + We need a method such as MillerIndex().as_tuple(). + + - Define a wrapper function for each function that we + want to expose, e.g.: + void add(const IndexingSet& ixset, const python::tuple PyMIx) + + The first alternative introduces a new type that the user has to + deal with. Other modules using Miller indices might organize them in + different ways, for example to increase runtime efficiency for + important procedures. This means, the user has to know how to + convert between the different kinds of Miller index representations. + This can quickly become a nuisance. Relying on native Python data + structures minimizes the number of special types the user has to + learn and convert. Of course, this argument is only valid for + small and relatively simply classes. + + If there are many member functions with MillerIndex arguments, the + second alternative is impractical, and concentrating the conversion + mechanism in one central place is essential for code + maintainability. An added benefit is that more convenient (smarter) + conversion functions can be provided without cluttering the rest of + the wrapper code. + + */ + +#include +#include +#include +namespace python = boost::python; + +namespace { // Avoid cluttering the global namespace. + + // The helper class. + // + class MillerIndex { + public: + int v[3]; + }; + + // The main class. Imagine that there are MANY member functions + // like add() and get(). + // + class IndexingSet { + private: + std::vector VMIx; + public: + void add(const MillerIndex& MIx) { VMIx.push_back(MIx); } + MillerIndex get(const std::size_t i) const { return VMIx[i]; } + }; +} + +BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE + + // Convert a Python tuple to a MillerIndex object. + // + MillerIndex from_python(PyObject* p, python::type) + { + python::tuple tup = python::tuple(python::ref(p)); + if (tup.size() != 3) { + PyErr_SetString(PyExc_ValueError, + "expecting exactly 3 values in tuple."); + throw python::error_already_set(); + } + MillerIndex result; + for (int i = 0; i < 3; i++) + result.v[i] = from_python(tup[i].get(), python::type()); + return result; + } + + // Similar conversion for MillerIndex objects passed by value. + // Not actually used, but included to show the principle. + // + MillerIndex from_python(PyObject* p, python::type) + { + return from_python(p, python::type()); + } + + // Convert a MillerIndex object to a Python tuple. + // + PyObject* to_python(const MillerIndex& hkl) + { + python::tuple result(3); + for (int i = 0; i < 3; i++) + result.set_item(i, to_python(hkl.v[i])); + return result.reference().release(); + } + +BOOST_PYTHON_END_CONVERSION_NAMESPACE + +extern "C" +DL_EXPORT(void) +initgetting_started5() +{ + try + { + // Create an object representing this extension module. + python::module_builder this_module("getting_started5"); + + // Create the Python type object for our extension class. + python::class_builder ixset_class(this_module, "IndexingSet"); + + // Add the __init__ function. + ixset_class.def(python::constructor<>()); + // Add the member functions. + ixset_class.def(&IndexingSet::add, "add"); + ixset_class.def(&IndexingSet::get, "get"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/ivect.cpp b/example/ivect.cpp new file mode 100644 index 00000000..f8ca8707 --- /dev/null +++ b/example/ivect.cpp @@ -0,0 +1,69 @@ +#include "ivect.h" +#include "dvect.h" +#include +#include +namespace python = boost::python; + +namespace { + + vects::dvect ivect_as_dvect(const vects::ivect& iv) + { + vects::dvect dv(iv.size()); + vects::dvect::iterator dviter = dv.begin(); + for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast(iv[i]); + return dv; + } + + boost::python::tuple dvect_as_tuple(const vects::dvect& dv) + { + return dv.as_tuple(); + } + + std::auto_ptr auto_ptr_dvect(const vects::ivect& iv) + { + return std::auto_ptr(new vects::dvect(ivect_as_dvect(iv))); + } + + boost::shared_ptr shared_ptr_dvect(const vects::ivect& iv) + { + return boost::shared_ptr(new vects::dvect(ivect_as_dvect(iv))); + } + + boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr& dv) + { + return dv->as_tuple(); + } + + boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr& dv) + { + return dv->as_tuple(); + } +} + +extern "C" +DL_EXPORT(void) +initivect() +{ + try + { + python::module_builder this_module("ivect"); + + python::x_class_builder ivect_class(this_module, "ivect"); + + python::import_class_builder dvect_class("dvect", "dvect"); + + ivect_class.def(python::constructor()); + ivect_class.def(&vects::ivect::as_tuple, "as_tuple"); + ivect_class.def(ivect_as_dvect, "as_dvect"); + + this_module.def(dvect_as_tuple, "dvect_as_tuple"); + ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect"); + ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect"); + this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple"); + this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/ivect.h b/example/ivect.h new file mode 100644 index 00000000..a0187307 --- /dev/null +++ b/example/ivect.h @@ -0,0 +1,32 @@ +#ifndef IVECT_H +#define IVECT_H + +#include +#include + +namespace vects { + + struct ivect : public std::vector + { + ivect() : std::vector() {} + ivect(size_t n) : std::vector(n) {} + ivect(boost::python::tuple tuple) : std::vector(tuple.size()) + { + std::vector::iterator v_it = begin(); + for (int i = 0; i < tuple.size(); i++) + v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(), + boost::python::type()); + } + + boost::python::tuple as_tuple() const + { + boost::python::tuple t(size()); + for (int i = 0; i < size(); i++) + t.set_item(i, + boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i]))); + return t; + } + }; +} + +#endif // IVECT_H diff --git a/example/noncopyable_export.cpp b/example/noncopyable_export.cpp new file mode 100644 index 00000000..82c3f049 --- /dev/null +++ b/example/noncopyable_export.cpp @@ -0,0 +1,24 @@ +#include +#include +namespace python = boost::python; + +#include "store.h" + +extern "C" +DL_EXPORT(void) +initnoncopyable_export() +{ + try + { + python::module_builder this_module("noncopyable_export"); + + python::xptr_class_builder store_class(this_module, "store"); + + store_class.def(python::constructor()); + store_class.def(&store::recall, "recall"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/noncopyable_import.cpp b/example/noncopyable_import.cpp new file mode 100644 index 00000000..529c9f42 --- /dev/null +++ b/example/noncopyable_import.cpp @@ -0,0 +1,42 @@ +#include +#include +namespace python = boost::python; + +#include "store.h" + +namespace { // Avoid cluttering the global namespace. + + // A function with store objects as both input and output parameters. + // Because the copy constructor is disabled, we cannot pass a store + // object by value. Instead, we pass a smart pointer. + std::auto_ptr add_stores(const store& s1, const store& s2) + { + int sum = s1.recall() + s2.recall(); + std::auto_ptr ss = std::auto_ptr(new store(sum)); + return ss; + } +} + +extern "C" +DL_EXPORT(void) +initnoncopyable_import() +{ + try + { + python::module_builder this_module("noncopyable_import"); + + python::import_class_builder + dvect_class("noncopyable_export", "store"); + + // Imagine all the additional classes with member functions + // that have store objects as input and output parameters. + // Lots and lots of them. + // However, to keep this example simple, we only define a + // module-level function. + this_module.def(add_stores, "add_stores"); + } + catch(...) + { + python::handle_exception(); // Deal with the exception for Python + } +} diff --git a/example/store.h b/example/store.h new file mode 100644 index 00000000..74ef0477 --- /dev/null +++ b/example/store.h @@ -0,0 +1,14 @@ +#ifndef STORE_H +#define STORE_H + +class store +{ + private: + store(const store&) { } // Disable the copy constructor. + int number; + public: + store(const int i) : number(i) { } + int recall() const { return number; } +}; + +#endif // STORE_H diff --git a/example/test_abstract.py b/example/test_abstract.py new file mode 100644 index 00000000..dda8aaa7 --- /dev/null +++ b/example/test_abstract.py @@ -0,0 +1,23 @@ +# Example by Ullrich Koethe +r'''>>> from abstract import * + >>> class A(Abstract): + ... def __init__(self, text): + ... Abstract.__init__(self) # call the base class constructor + ... self.text = text + ... def test(self): # implement abstract function + ... return self.text + ... + >>> a = A("Hello") + >>> a.test() + 'Hello' +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_abstract + doctest.testmod(test_abstract) + +if __name__ == '__main__': + run() diff --git a/example/test_example1.py b/example/test_example1.py deleted file mode 100644 index 0e3a9a18..00000000 --- a/example/test_example1.py +++ /dev/null @@ -1,50 +0,0 @@ -r''' -// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of Dragon Systems, Inc., in -// producing this work. - -That's it! If we build this shared library and put it on our PYTHONPATH we can -now access our C++ class and function from Python. - - >>> import hello - >>> hi_world = hello.world(3) - >>> hi_world.get() - 'hi, world' - >>> hello.length(hi_world) - 9 - -We can even make a subclass of hello.world: - - - >>> class my_subclass(hello.world): - ... def get(self): - ... return 'hello, world' - ... - >>> y = my_subclass(2) - >>> y.get() - 'hello, world' - -Pretty cool! You can't do that with an ordinary Python extension type! - - >>> hello.length(y) - 9 - -Of course, you may now have a slightly empty feeling in the pit of your little -pythonic stomach. Perhaps you feel your subclass deserves to have a length() of -12? If so, read on... -''' -from hello import * - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_example1 - doctest.testmod(test_example1) - -if __name__ == '__main__': - run() diff --git a/example/test_getting_started1.py b/example/test_getting_started1.py new file mode 100644 index 00000000..7daf65af --- /dev/null +++ b/example/test_getting_started1.py @@ -0,0 +1,17 @@ +r'''>>> import getting_started1 + >>> print getting_started1.greet() + hello, world + >>> number = 11 + >>> print number, '*', number, '=', getting_started1.square(number) + 11 * 11 = 121 +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_getting_started1 + doctest.testmod(test_getting_started1) + +if __name__ == '__main__': + run() diff --git a/example/test_getting_started2.py b/example/test_getting_started2.py new file mode 100644 index 00000000..09215816 --- /dev/null +++ b/example/test_getting_started2.py @@ -0,0 +1,19 @@ +r'''>>> import getting_started2 + >>> w = getting_started2.world('California') + >>> print w.greet() + Hello from California! + >>> print getting_started2.invite(w) + Hello from California! Please come soon! + >>> print w.invite() + Hello from California! Please come soon! +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_getting_started2 + doctest.testmod(test_getting_started2) + +if __name__ == '__main__': + run() diff --git a/example/test_getting_started3.py b/example/test_getting_started3.py new file mode 100644 index 00000000..d62cf5a2 --- /dev/null +++ b/example/test_getting_started3.py @@ -0,0 +1,56 @@ +r'''>>> import getting_started3 + >>> import re + >>> import pickle + >>> getting_started3.world.__module__ + 'getting_started3' + >>> getting_started3.world.__safe_for_unpickling__ + 1 + >>> getting_started3.world.__reduce__() + 'world' + >>> assert re.match( + ... "\(, \('Hello',\), \(0,\)\)", + ... repr(getting_started3.world('Hello').__reduce__())) + >>> + >>> for number in (24, 42): + ... wd = getting_started3.world('California') + ... wd.set_secret_number(number) + ... pstr = pickle.dumps(wd) + ... print pstr + ... wl = pickle.loads(pstr) + ... print wd.greet(), wd.get_secret_number() + ... print wl.greet(), wl.get_secret_number() + cgetting_started3 + world + p0 + (S'California' + p1 + tp2 + R(I24 + tp3 + bp4 + . + Hello from California! 24 + Hello from California! 24 + cgetting_started3 + world + p0 + (S'California' + p1 + tp2 + R(I42 + tp3 + bp4 + . + Hello from California! 42 + Hello from California! 0 +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_getting_started3 + doctest.testmod(test_getting_started3) + +if __name__ == '__main__': + run() diff --git a/example/test_getting_started4.py b/example/test_getting_started4.py new file mode 100644 index 00000000..82b5c794 --- /dev/null +++ b/example/test_getting_started4.py @@ -0,0 +1,35 @@ +r'''>>> import getting_started4 + >>> v=getting_started4.vector_double() + >>> print v.as_tuple() + () + >>> v=getting_started4.vector_double(5) + >>> print v.as_tuple() + (0.0, 0.0, 0.0, 0.0, 0.0) + >>> print len(v) + 5 + >>> v=getting_started4.vector_double((3,4,5)) + >>> print v.as_tuple() + (3.0, 4.0, 5.0) + >>> print v[1] + 4.0 + >>> v[1] = 40 + >>> print v.as_tuple() + (3.0, 40.0, 5.0) + >>> del v[1] + >>> print v.as_tuple() + (3.0, 5.0) + >>> print getting_started4.foo(11).as_tuple() + (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) + >>> print getting_started4.bar(12).as_tuple() + (0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_getting_started4 + doctest.testmod(test_getting_started4) + +if __name__ == '__main__': + run() diff --git a/example/test_getting_started5.py b/example/test_getting_started5.py new file mode 100644 index 00000000..8eeba1e2 --- /dev/null +++ b/example/test_getting_started5.py @@ -0,0 +1,22 @@ +r'''>>> import getting_started5 + >>> ixset = getting_started5.IndexingSet() + >>> ixset.add((1,2,3)) + >>> ixset.add((4,5,6)) + >>> ixset.add((7,8,9)) + >>> print ixset.get(0) + (1, 2, 3) + >>> print ixset.get(1) + (4, 5, 6) + >>> print ixset.get(2) + (7, 8, 9) +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_getting_started5 + doctest.testmod(test_getting_started5) + +if __name__ == '__main__': + run() diff --git a/example/test_rwgk1.py b/example/test_rwgk1.py deleted file mode 100644 index 87298875..00000000 --- a/example/test_rwgk1.py +++ /dev/null @@ -1,17 +0,0 @@ -r'''>>> import rwgk1 - >>> print rwgk1.greet() - hello, world - >>> number = 11 - >>> print number, '*', number, '=', rwgk1.square(number) - 11 * 11 = 121 -''' - -def run(args = None): - if args is not None: - import sys - sys.argv = args - import doctest, test_rwgk1 - doctest.testmod(test_rwgk1) - -if __name__ == '__main__': - run() diff --git a/example/tst_dvect.py b/example/tst_dvect.py new file mode 100644 index 00000000..563f0ad5 --- /dev/null +++ b/example/tst_dvect.py @@ -0,0 +1,16 @@ +import dvect +print dvect.dvect.__converters__ +dv = dvect.dvect((1,2,3,4,5)) +print dv +print dv.as_tuple() +iv = dv.as_ivect() +print iv +print iv.as_tuple() +print dvect.ivect_as_tuple(iv) +aiv = dv.auto_ptr_ivect() +print aiv +siv = dv.shared_ptr_ivect() +print dvect.auto_ptr_ivect_as_tuple(aiv) +print dvect.ivect_as_tuple(aiv) +print dvect.shared_ptr_ivect_as_tuple(siv) +print dvect.ivect_as_tuple(siv) diff --git a/example/tst_ivect.py b/example/tst_ivect.py new file mode 100644 index 00000000..58bc323f --- /dev/null +++ b/example/tst_ivect.py @@ -0,0 +1,16 @@ +import ivect +print ivect.ivect.__converters__ +iv = ivect.ivect((1,2,3,4,5)) +print iv +print iv.as_tuple() +dv = iv.as_dvect() +print dv +print dv.as_tuple() +print ivect.dvect_as_tuple(dv) +adv = iv.auto_ptr_dvect() +print adv +sdv = iv.shared_ptr_dvect() +print ivect.auto_ptr_dvect_as_tuple(adv) +print ivect.dvect_as_tuple(adv) +print ivect.shared_ptr_dvect_as_tuple(sdv) +print ivect.dvect_as_tuple(sdv) diff --git a/example/tst_noncopyable.py b/example/tst_noncopyable.py new file mode 100644 index 00000000..913df039 --- /dev/null +++ b/example/tst_noncopyable.py @@ -0,0 +1,8 @@ +import noncopyable_export +import noncopyable_import +s1 = noncopyable_export.store(1) +print s1.recall() +s2 = noncopyable_export.store(2) +print s2.recall() +s3 = noncopyable_import.add_stores(s1, s2) +print s3.recall()