diff --git a/src/indexing/python_iterator.cpp b/src/indexing/python_iterator.cpp new file mode 100755 index 00000000..015171a4 --- /dev/null +++ b/src/indexing/python_iterator.cpp @@ -0,0 +1,168 @@ +// -*- mode:c++ -*- +// +// Module python_iterator.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#include + +//////////////////////////////////////////////////////////////////////////// +// python_iterator factory +/////////////////////////////////////////////////////////////////////////// + +std::auto_ptr +boost::python::indexing::make_iterator (boost::python::object temp) +{ + std::auto_ptr result; + + try + { + result.reset (new python_iter_iterator (temp)); + } + + catch (boost::python::error_already_set const &) + { + PyErr_Clear (); + + try + { + result.reset (new python_getitem_iterator (temp)); + } + + catch (boost::python::error_already_set const &) + { + PyErr_Clear (); + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////// +// Base class (virtual) destructor +/////////////////////////////////////////////////////////////////////////// + +boost::python::indexing::python_iterator::~python_iterator () +{ +} + +//////////////////////////////////////////////////////////////////////////// +// python_getitem_iterator constructor +/////////////////////////////////////////////////////////////////////////// + +boost::python::indexing::python_getitem_iterator +::python_getitem_iterator (boost::python::object obj) + : mGetitemMethod (obj.attr ("__getitem__")) + , mIndex (0) + , mCurrent() +{ +} + +//////////////////////////////////////////////////////////////////////////// +// Get our next item (if any) +/////////////////////////////////////////////////////////////////////////// + +bool boost::python::indexing::python_getitem_iterator::next () +{ + bool result = true; // Assume success + + try + { + mCurrent = mGetitemMethod (mIndex); + ++mIndex; + } + + catch (boost::python::error_already_set const &) + { + if (PyErr_ExceptionMatches (PyExc_IndexError)) + { + // Eat this exception + PyErr_Clear (); + mCurrent = boost::python::object (); + result = false; + } + + else + { + // Pass it up the line + throw; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////// +// Return our current item +/////////////////////////////////////////////////////////////////////////// + +boost::python::object +boost::python::indexing::python_getitem_iterator::current () const +{ + return mCurrent; +} + +//////////////////////////////////////////////////////////////////////////// +// python_iter_iterator constructor +/////////////////////////////////////////////////////////////////////////// + +boost::python::indexing::python_iter_iterator +::python_iter_iterator (boost::python::object obj) + : mNextMethod (obj.attr ("__iter__")().attr ("next")) + , mCurrent() +{ +} + +//////////////////////////////////////////////////////////////////////////// +// Get our next item (if any) +/////////////////////////////////////////////////////////////////////////// + +bool boost::python::indexing::python_iter_iterator::next () +{ + bool result = true; // Assume success + + try + { + mCurrent = mNextMethod (); + } + + catch (boost::python::error_already_set const &) + { + if (PyErr_ExceptionMatches (PyExc_StopIteration)) + { + // Eat this exception + PyErr_Clear (); + mCurrent = boost::python::object (); + result = false; + } + + else + { + // Pass it up the line + throw; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////// +// Return our current item +/////////////////////////////////////////////////////////////////////////// + +boost::python::object +boost::python::indexing::python_iter_iterator::current () const +{ + return mCurrent; +} diff --git a/src/indexing/slice.cpp b/src/indexing/slice.cpp new file mode 100755 index 00000000..cfd740bb --- /dev/null +++ b/src/indexing/slice.cpp @@ -0,0 +1,65 @@ +// -*- mode:c++ -*- +// +// Module slice.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#include + +///////////////////////////////////////////////////////////////////////////// +// Check that setLength has been called, and throw otherwise +///////////////////////////////////////////////////////////////////////////// + +void boost::python::indexing::slice::validate () const +{ + if (mDirection == 0) + { + PyErr_SetString (PyExc_RuntimeError + , "slice access attempted before setLength called"); + boost::python::throw_error_already_set(); + } +} + +///////////////////////////////////////////////////////////////////////////// +// Set up our member variables for a sequence of a given length +///////////////////////////////////////////////////////////////////////////// + +void boost::python::indexing::slice::setLength (int sequenceLength) +{ + PySlice_GetIndices ((PySliceObject *) this->ptr() + , sequenceLength + , &mStart + , &mStop + , &mStep); + + if (mStep == 0) + { + // Can happen with Python prior to 2.3 + PyErr_SetString (PyExc_ValueError, "slice step cannot be zero"); + boost::python::throw_error_already_set (); + } + + mStart = std::max (0, std::min (sequenceLength, mStart)); + mStop = std::max (0, std::min (sequenceLength, mStop)); + mDirection = (mStep > 0) ? 1 : -1; +} + +///////////////////////////////////////////////////////////////////////////// +// Check if an index is within the range of this slice +///////////////////////////////////////////////////////////////////////////// + +bool boost::python::indexing::slice::inRange (int index) +{ + return ((mStop - index) * mDirection) > 0; +} diff --git a/test/IntWrapper.hpp b/test/IntWrapper.hpp new file mode 100755 index 00000000..4204ab0e --- /dev/null +++ b/test/IntWrapper.hpp @@ -0,0 +1,174 @@ +// -*- mode:c++ -*- +// +// Header file IntWrapper.hpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#ifndef IntWrapper_rmg_20030910_included +#define IntWrapper_rmg_20030910_included + +#include +#include + +struct IntWrapper { + static bool gIntWrapperTrace; + static unsigned ourObjectCounter; + int mObjNumber; + int mI; + + inline IntWrapper (); + inline explicit IntWrapper (int i); + inline IntWrapper (IntWrapper const &other); + inline IntWrapper &operator= (IntWrapper const &other); + inline ~IntWrapper (); + + inline void increment(); + + inline operator boost::shared_ptr () const; + + inline static void setTrace (int onoff); +}; + +inline bool operator== (IntWrapper const &lhs, IntWrapper const &rhs); +inline bool operator< (IntWrapper const &lhs, IntWrapper const &rhs); +inline int compare (IntWrapper const &lhs, IntWrapper const &rhs); +inline std::ostream &operator<< (std::ostream &strm, IntWrapper const &iw); + +// +// This is ugly. Put all of this stuff inline to avoid needing a +// separate object file for testing (don't know how to do this in +// Jam). Client module will have to define the following variables: +// +// bool IntWrapper::gIntWrapperTrace = true; +// unsigned IntWrapper::ourObjectCounter = 0; +// + +IntWrapper::IntWrapper () + : mObjNumber (ourObjectCounter++) + , mI (0) +{ + if (gIntWrapperTrace) + { + printf ("IntWrapper %u ()\n", mObjNumber); + } +} + +IntWrapper::IntWrapper (int i) + : mObjNumber (ourObjectCounter++) + , mI (i) +{ + if (gIntWrapperTrace) + { + printf ("IntWrapper %u (%d)\n" + , mObjNumber + , mI); + } +} + +IntWrapper::IntWrapper (IntWrapper const &other) + : mObjNumber (ourObjectCounter++) + , mI (other.mI) +{ + if (gIntWrapperTrace) + { + printf ("IntWrapper %u (IntWrapper %u)\n" + , mObjNumber + , other.mObjNumber); + } +} + +IntWrapper &IntWrapper::operator= (IntWrapper const &other) +{ + if (gIntWrapperTrace) + { + printf ("IntWrapper %u = IntWrapper %u\n" + , mObjNumber + , other.mObjNumber); + } + + mI = other.mI; + + return *this; +} + +IntWrapper::~IntWrapper () +{ + if (gIntWrapperTrace) + { + printf ("~IntWrapper %u\n", mObjNumber); + } + + mI = 0xbaaaaaad; +} + +void IntWrapper::increment() +{ + if (gIntWrapperTrace) + { + printf ("IntWrapper %u::increment\n", mObjNumber); + } + + ++mI; +} + +IntWrapper::operator boost::shared_ptr () const +{ + if (gIntWrapperTrace) + { + printf ("IntWrapper %u shared_ptr conversion\n", mObjNumber); + } + + return boost::shared_ptr (new IntWrapper (*this)); +} + +void IntWrapper::setTrace (int onoff) +{ + gIntWrapperTrace = onoff; +} + +bool operator== (IntWrapper const &lhs, IntWrapper const &rhs) +{ + return lhs.mI == rhs.mI; +} + +bool operator< (IntWrapper const &lhs, IntWrapper const &rhs) +{ + return lhs.mI < rhs.mI; +} + +int compare (IntWrapper const &lhs, IntWrapper const &rhs) +{ + if (lhs < rhs) + { + return -1; + } + + else if (rhs < lhs) + { + return 1; + } + + else + { + return 0; + } +} + +std::ostream &operator<< (std::ostream &strm, IntWrapper const &iw) +{ + strm << iw.mI; + return strm; +} + +#endif // IntWrapper_rmg_20030910_included diff --git a/test/test_array.py b/test/test_array.py new file mode 100644 index 00000000..ec28dfa3 --- /dev/null +++ b/test/test_array.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_array.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +'''>>> from testlinear import * +>>> setTrace (0) +>>> v = getArray() +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + from test_array_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_array_common.py b/test/test_array_common.py new file mode 100644 index 00000000..46818eee --- /dev/null +++ b/test/test_array_common.py @@ -0,0 +1,109 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_array_common.py +# +# Shared doctest sequence for use with any array-based container +# (including vectors). Performs tests that do not require insertion or +# deletion. +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +# +# Note - on entry, v must be the container for testing, and it +# must already contain the correct sequence of elements. +# + +'''>>> print [ x for x in v ] +[8, 6, 4, 2, 1, 3, 5, 7, 0] +>>> print len(v) +9 +>>> print v.count (9) # Count with no matches +0 +>>> print v.count (2) # Count with unique match +1 +>>> print v.index (0) # Index with match +8 +>>> assert 0 in v # contains with match +>>> assert 8 in v # contains with match +>>> assert not -1 in v # contains without match +>>> print v[0] # Get first element OK (zero index) +8 +>>> print v[len(v)-1] # Get last element OK (+ve index) +0 +>>> print v[-1] # Get last element OK (-ve index) +0 +>>> print v[-len(v)] # Get first element OK (-ve index) +8 +>>> v[0] = 9 # Replace first element OK (zero index) +>>> print [ x for x in v ] +[9, 6, 4, 2, 1, 3, 5, 7, 0] +>>> v[len(v)-1] = 1 # Replace last element OK (+ve index) +>>> print [ x for x in v ] +[9, 6, 4, 2, 1, 3, 5, 7, 1] +>>> v[-1] = 0 # Replace last element OK (-ve index) +>>> print [ x for x in v ] +[9, 6, 4, 2, 1, 3, 5, 7, 0] +>>> v[-len(v)] = 8 # Replace first element OK (-ve index) +>>> print [ x for x in v ] +[8, 6, 4, 2, 1, 3, 5, 7, 0] +>>> try: +... print v[len(v)] # Get element index out of range +... except IndexError, e: +... print "Got expected exception" +... +Got expected exception +>>> try: +... print v[-(len(v)+1)] # Get element index out of range (-ve) +... except IndexError, e: +... print "Got expected exception" +... +Got expected exception +>>> try: +... v[len(v)] = 9 # Set element index out of range +... except IndexError, e: +... print "Got expected exception" +... +Got expected exception +>>> try: +... print v.index (9) # Search for nonexistant value +... except ValueError, e: +... print "Got expected exception" +... +Got expected exception +>>> v.reverse() # Reverse +>>> print [ x for x in v ] +[0, 7, 5, 3, 1, 2, 4, 6, 8] +>>> v.sort() # Sort +>>> print [ x for x in v ] +[0, 1, 2, 3, 4, 5, 6, 7, 8] +>>> v[0] = 8 # Single element replace +>>> print v.count(8) # Count with multiple matches +2 +>>> print v[v.index(3)] # Check index and lookup +3 +>>> v[:] = [4, 5, 6, 7, 8, 8, 1, 2, 3] # Equal length slice replace (list) +>>> print [ x for x in v ] +[4, 5, 6, 7, 8, 8, 1, 2, 3] +>>> print [ x for x in v[7:] ] # Slice from index to end +[2, 3] +>>> print [ x for x in v[-2:] ] # Slice from two before end to end +[2, 3] +>>> print [ x for x in v[-2:99999] ] # Slice with high end index +[2, 3] +>>> print [ x for x in v[99999:] ] # Slice with high start index +[] +''' + +common_doctest_string = __doc__ diff --git a/test/test_list_plain.py b/test/test_list_plain.py new file mode 100644 index 00000000..107ac5ac --- /dev/null +++ b/test/test_list_plain.py @@ -0,0 +1,60 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_list_plain.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +'''>>> from testlinear import * +>>> setTrace(0) +>>> l = List() +>>> assert not 0 in l # Search in empty list +>>> l.append (1) # Append +>>> l.append (2) +>>> l.append (3) +>>> print [ x for x in l ] # Iteration +[1, 2, 3] +>>> assert 2 in l # Successful search +>>> assert not 4 in l # Unsuccessful search +>>> print l.count(3) # Found item +1 +>>> print l.count(-1) # Not found item +0 +>>> l.reverse() # Reverse +>>> print [ x for x in l ] +[3, 2, 1] +>>> l.sort() # Sort +>>> print [ x for x in l ] +[1, 2, 3] +>>> print len(l) # Length +3 +>>> for x in l: +... x.increment() # Check value semantics +... +>>> print [ x for x in l ] # Container should be unchanged +[1, 2, 3] +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_map_plain.py b/test/test_map_plain.py new file mode 100644 index 00000000..719adbb0 --- /dev/null +++ b/test/test_map_plain.py @@ -0,0 +1,77 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_map_plain.py +# +# Doctest-based testing for a C++ map. +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +'''>>> from testnonlinear import * +>>> setTrace(0) +>>> m = Map() # std::map +>>> m["hello"] = 1 # Insert entry +>>> print m["hello"] # Lookup entry +1 +>>> m.insert ("Barnaby", 2) +>>> print m["Barnaby"] +2 +>>> m["Barnaby"] = 3 +>>> print m["Barnaby"] +3 +>>> assert m.has_key ("Barnaby") +>>> assert "hello" in m +>>> assert "Barnaby" in m +>>> print m.count ("Barnaby") +1 +>>> m.insert ("world", 4) +>>> print m["world"] +4 +>>> try: +... m.insert ("Barnaby", 2) +... except ValueError, e: +... print "Got expected exception:", e +... +Got expected exception: Map already holds value for insertion +>>> del m["Barnaby"] +>>> try: +... print m["Barnaby"] +... except ValueError, e: +... print "Got expected exception:", e +... +Got expected exception: associative container: key not found +>>> try: +... del m["Barnaby"] +... except ValueError, e: +... print "Got expected exception:", e +... +Got expected exception: Container does not hold value to be erased +>>> print m["hello"] +1 +>>> print m["world"] +4 +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_python_list.py b/test/test_python_list.py new file mode 100644 index 00000000..ca92979f --- /dev/null +++ b/test/test_python_list.py @@ -0,0 +1,35 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_python_list.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +'''>>> v = [] +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + from test_vector_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_set_plain.py b/test/test_set_plain.py new file mode 100644 index 00000000..0adc3580 --- /dev/null +++ b/test/test_set_plain.py @@ -0,0 +1,77 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_set_plain.py +# +# Doctest-based testing for a C++ set. +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +'''>>> from testnonlinear import * +>>> setTrace(0) +>>> s = Set() # std::set +>>> s["hello"] = None # Insert entry (weird interface) +>>> print s["hello"] # Lookup entry +hello +>>> s.insert ("Barnaby") # Insert entry (sensible interface) +>>> print s["Barnaby"] +Barnaby +>>> assert s.has_key ("Barnaby") +>>> assert not s.has_key ("Rudge") +>>> assert "hello" in s +>>> assert "Barnaby" in s +>>> print s.count ("Barnaby") +1 +>>> s.insert ("world") +>>> print s["world"] +world +>>> try: +... s.insert ("Barnaby") +... except ValueError, e: +... print "Got expected exception:", e +... +Got expected exception: Set already holds value for insertion +>>> del s["Barnaby"] +>>> try: +... print s["Barnaby"] +... except ValueError, e: +... print "Got expected exception:", e +... +Got expected exception: associative container: key not found +>>> try: +... del s["Barnaby"] +... except ValueError, e: +... print "Got expected exception:", e +... +Got expected exception: Container does not hold value to be erased +>>> print s["hello"] +hello +>>> print s["world"] +world +>>> print [ x for x in s ] +['hello', 'world'] +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_vector_common.py b/test/test_vector_common.py new file mode 100644 index 00000000..29866ba1 --- /dev/null +++ b/test/test_vector_common.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_vector_common.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/ 9/29 rmg File creation +# +# $Id$ +# + +'''>>> del v[:] # Clear container if ncessary +>>> del v[:] # Check slice delete on empty container +>>> print v[:] # Check slice get on empty container +[] +>>> v[:] = [] # Check slice set on empty container +>>> print [ x for x in v ] # Iterate over empty container +[] +>>> try: +... print v.index (2) # Search in empty container +... except ValueError, e: +... print "Got expected exception" +... +Got expected exception +>>> print v.count (2) # Search in empty container +0 +>>> print len(v) # Length of empty container +0 +>>> v.extend ([1, 3, 5, 2, 4, 6]) # Try extend with Python list +>>> print len(v) # Length of non-empty container +6 +>>> print [ x for x in v ] # Iteration +[1, 3, 5, 2, 4, 6] +>>> v.reverse() # Reverse +>>> print [ x for x in v ] +[6, 4, 2, 5, 3, 1] +>>> v.sort() # Sort +>>> print [ x for x in v ] +[1, 2, 3, 4, 5, 6] +>>> v[:] = [3, 4] # Remove dependencies on prior results +>>> v.insert (0, 2) # Insert at start +>>> print [ x for x in v ] +[2, 3, 4] +>>> v.insert (len(v), 5) # Insert at end +>>> print [ x for x in v ] +[2, 3, 4, 5] +>>> v.insert (999, 6) # Insert at end (out of bounds) +>>> print [ x for x in v ] +[2, 3, 4, 5, 6] +>>> v.insert (-1, 1) # Insert at beginning (-ve) +>>> print [ x for x in v ] +[1, 2, 3, 4, 5, 6] +>>> v.append (7) # Append +>>> print [ x for x in v ] +[1, 2, 3, 4, 5, 6, 7] +>>> v.extend ([3,8,9,10]) # Extend +>>> print [ x for x in v ] +[1, 2, 3, 4, 5, 6, 7, 3, 8, 9, 10] +>>> del v[2] # Single element delete +>>> print [ x for x in v ] +[1, 2, 4, 5, 6, 7, 3, 8, 9, 10] +>>> del v[-2:] # Delete slice (one negative index) +>>> print [ x for x in v ] +[1, 2, 4, 5, 6, 7, 3, 8] +>>> v[-2:-1] = [] # Delete slice via __setitem__ +>>> print [ x for x in v ] +[1, 2, 4, 5, 6, 7, 8] +>>> v [-2:-1] = [9, 10] # Replace and insert via slice +>>> print [ x for x in v ] +[1, 2, 4, 5, 6, 9, 10, 8] +>>> try: +... del v[len(v)] # Delete element index out of range +... except IndexError, e: +... print "Got expected exception" +... +Got expected exception +>>> try: +... del v[-(len(v) + 2)] # Delete negative index out of range +... except IndexError, e: +... print "Got expected exception" +... +Got expected exception +>>> v.insert (len(v) + 1, 0) # Insert at end via out of range +>>> print [ x for x in v ] +[1, 2, 4, 5, 6, 9, 10, 8, 0] +>>> v.insert (-1, 7) # Insert at beginning via negative +>>> print [ x for x in v ] +[7, 1, 2, 4, 5, 6, 9, 10, 8, 0] +>>> v[:] = [8, 6, 4, 2, 1, 3, 5, 7, 0] # Prepare for common array tests +''' + +import test_array_common + +common_doctest_string = __doc__ + test_array_common.common_doctest_string diff --git a/test/test_vector_plain.py b/test/test_vector_plain.py new file mode 100644 index 00000000..bc4f9993 --- /dev/null +++ b/test/test_vector_plain.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_vector_plain.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/ 9/29 rmg File creation +# +# $Id$ +# + +'''>>> from testlinear import * +>>> v = Vector() +>>> v[:] = (6, 7, 8, 5, 4, 8, 3, 1, 2) # Slice replace (tuple) +>>> print [ x for x in v ] +[6, 7, 8, 5, 4, 8, 3, 1, 2] +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + from test_vector_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_vector_proxy.py b/test/test_vector_proxy.py new file mode 100644 index 00000000..3398e43f --- /dev/null +++ b/test/test_vector_proxy.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_vector_proxy.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/ 9/29 rmg File creation +# +# $Id$ +# + +'''>>> from testlinear import * +>>> setTrace(False) +>>> v = Vector_proxy() +>>> v.extend ([6, 5, 4, 3]) +>>> print [ x for x in v ] +[6, 5, 4, 3] +>>> for x in v: +... x.increment() # Check iterator provides by-ref access +... +>>> print [ x for x in v ] # Check mutation happened in container +[7, 6, 5, 4] +>>> v0 = v[0] # Reference to first element +>>> v3 = v[3] # Reference to last element +>>> print v0, v[0], v3 # Check reference values +7 7 4 +>>> v0.increment() # Increment one of the referenced elements +>>> print v0, v[0], v3 # Check reference to same object +8 8 4 +>>> v[:0] = [3] # Insert before any referenced elements +>>> print [ x for x in v ] # Check whole contents +[3, 8, 6, 5, 4] +>>> print v0, v[1], v3 # Check references to original elements +8 8 4 +>>> v[1].increment() # Increment element in container +>>> print v0, v[1], v3 # Check reference to same object +9 9 4 +>>> del v[1] # Delete element from container +>>> print v0, v[1], v3 # Check old element value copied +9 6 4 +>>> print [ x for x in v ] # Check container contents +[3, 6, 5, 4] +>>> v0 = v[0] # Get new reference to first element +>>> print v0, v[0] # Check matching +3 3 +>>> v[0] = 9 # Overwrite first element +>>> print v0, v[0] # Check old value copied +3 9 +>>> v_slice1 = v[1:3] # Slice for v[1] and v[2] +>>> v_slice2 = v[1:3] # Same slice again +>>> print v_slice1, v_slice2, v[1], v[2] +[6, 5] [6, 5] 6 5 +>>> v[1].increment() # Check all refer to same v[1] +>>> print v_slice1, v_slice2, v[1], v[2] +[7, 5] [7, 5] 7 5 +>>> v_slice1[1].increment() # Check all refer to same v[2] +>>> print v_slice1, v_slice2, v[1], v[2] +[7, 6] [7, 6] 7 6 +>>> v[2:2] = [10] # Insert within slice range +>>> print v_slice1, v_slice2, v[1], v[2], v[3] +[7, 6] [7, 6] 7 10 6 +>>> v_slice1[1] = 9 # Replace one reference +>>> print v_slice1, v_slice2, v[1], v[2], v[3] # Check no side-effects +[7, 9] [7, 6] 7 10 6 +>>> del v[1:4] # Remove whole slice +>>> print v_slice1, v_slice2, v[1] # Check reference copies +[7, 9] [7, 6] 4 +>>> v_slice1[0].increment() # Mutate shared object +>>> print v_slice1, v_slice2, v[1] # Check reference to same object +[8, 9] [8, 6] 4 +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + from test_vector_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/test_vector_ref.py b/test/test_vector_ref.py new file mode 100644 index 00000000..02bee502 --- /dev/null +++ b/test/test_vector_ref.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_vector_ref.py +# +# Test the vector container with return_internal_reference +# policies. This is a dangerous container - see the container suite +# documentation on using policies for details. +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/ 1 rmg File creation +# +# $Id$ +# + +'''>>> from testlinear import * +>>> setTrace(False) +>>> v = Vector_ref() +>>> v.append (3) +>>> ref = v[0] +>>> print ref, v[0] +3 3 +>>> v[0].increment() # Mutate object in container +>>> print ref, v[0] # Check reference refers to same object +4 4 +>>> for x in v: +... x.increment() # Check iterator provides by-ref access +... +>>> print ref, v[0] # Check mutation happened in container element +5 5 +>>> # DO NOT try insert and delete, since the element reference +>>> # would be invalidated by those operations. +>>> del ref # Avoid dangling reference during subsequent tests +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + from test_vector_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + sys.exit(run()[0]) diff --git a/test/testlinear.cpp b/test/testlinear.cpp new file mode 100755 index 00000000..ba1c427a --- /dev/null +++ b/test/testlinear.cpp @@ -0,0 +1,119 @@ +// -*- mode:c++ -*- +// +// Module testlinear.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/ 8 rmg File creation as testsuite.cpp +// 2003/ 9/29 rmg Renamed testlinear.cpp to allow division into parts +// +// $Id$ +// + +#include "IntWrapper.hpp" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +bool IntWrapper::gIntWrapperTrace = true; +unsigned IntWrapper::ourObjectCounter = 0; + +boost::python::indexing::iterator_pair getArray() +{ + static IntWrapper array[] = { + IntWrapper(8), IntWrapper(6), IntWrapper(4), IntWrapper(2) + , IntWrapper(1), IntWrapper(3), IntWrapper(5) + , IntWrapper(7), IntWrapper(0) }; + + return boost::python::indexing::iterator_pair + (boost::python::indexing::begin(array) + , boost::python::indexing::end(array)); +} + +std::string repr (IntWrapper const &i) +{ + std::stringstream temp; + temp << i; + return temp.str(); +} + +BOOST_PYTHON_MODULE(testlinear) +{ + boost::python::implicitly_convertible (); + + boost::python::def ("setTrace", &IntWrapper::setTrace); + + boost::python::class_ ("IntWrapper", boost::python::init()) + .def ("increment", &IntWrapper::increment) + .def ("__repr__", repr) + .def ("__cmp__", compare) + ; + + typedef std::vector Container1; + + boost::python::class_("Vector") + .def (boost::python::indexing::container_suite()) + .def ("reserve", &Container1::reserve) + ; + + typedef std::list Container2; + + boost::python::class_("List") + .def (boost::python::indexing::container_suite()); + + typedef boost::python::indexing::iterator_pair Container3; + + boost::python::class_ + ("Array", boost::python::init()) + .def (boost::python::indexing::container_suite()); + + boost::python::def ("getArray", getArray); + + typedef std::vector Container4; + + // Returning internal references to elements of a vector is + // dangerous! The references can be invalidated by inserts or + // deletes! + boost::python::class_("Vector_ref") + .def (boost::python::indexing::container_suite + ::with_policies (boost::python::return_internal_reference<>())); + + typedef boost::python::indexing::container_proxy< std::vector > + Container5; + + boost::python::class_("Vector_proxy") + .def (boost::python::indexing::container_suite()) + .def ("reserve", &Container5::reserve) + ; + + /* The no-partial-specialization version for vector + + using namespace boost::python; + using namespace indexing; + + class_ > ("vector_int") + .def (visitor < + default_algorithms < + default_sequence_traits < + std::vector > >, + return_value_policy + >()); + */ +} diff --git a/test/testnonlinear.cpp b/test/testnonlinear.cpp new file mode 100755 index 00000000..93feb6ef --- /dev/null +++ b/test/testnonlinear.cpp @@ -0,0 +1,63 @@ +// -*- mode:c++ -*- +// +// Module testnonlinear.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/ 9/29 rmg File creation from testlinear.cpp +// +// $Id$ +// + +#include "IntWrapper.hpp" +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +bool IntWrapper::gIntWrapperTrace = true; +unsigned IntWrapper::ourObjectCounter = 0; + +std::string repr (IntWrapper const &i) +{ + std::stringstream temp; + temp << i; + return temp.str(); +} + +BOOST_PYTHON_MODULE(testnonlinear) +{ + boost::python::implicitly_convertible (); + + boost::python::def ("setTrace", &IntWrapper::setTrace); + + boost::python::class_ ("IntWrapper", boost::python::init()) + .def ("increment", &IntWrapper::increment) + .def ("__repr__", repr) + .def ("__cmp__", compare) + ; + + typedef std::map Container1; + + boost::python::class_("Map") + .def (boost::python::indexing::container_suite()); + + typedef std::set Container2; + + boost::python::class_("Set") + .def (boost::python::indexing::container_suite()); + +}