PySequenceHolder.h

Go to the documentation of this file.
00001 //
00002 // Copyright (c) 2003-2006 greg Landrum and Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved @@
00005 //  This file is part of the RDKit.
00006 //  The contents are covered by the terms of the BSD license
00007 //  which is included in the file license.txt, found at the root
00008 //  of the RDKit source tree.
00009 //
00010 
00011 #ifndef _RD_PYSEQUENCEHOLDER_H_
00012 #define _RD_PYSEQUENCEHOLDER_H_
00013 
00014 //
00015 // Defines a class to hold sequences passed in from Python
00016 //
00017 #include "Wrap.h"
00018 #include <RDGeneral/Invariant.h>
00019 
00020 namespace python = boost::python;
00021 
00022 //! \brief Class to hold sequences (lists, tuples, arrays, etc.)
00023 //!         passed from Python -> C++
00024 //!
00025 //!  PySequenceHolder is templated on the type of the contained object.
00026 //!
00027 //!  The class is \em lazy: elements are not evaluated until requested
00028 //!     within the C++ code.
00029 //!
00030 template <typename T>
00031 class PySequenceHolder {
00032 public:
00033   PySequenceHolder(python::object seq) {
00034     d_seq = seq;
00035   };
00036 
00037   // --------------------------------------------------
00038   //! \brief Returns the size of the contained sequence.
00039   //!
00040   //! NOTE: the sequence must have a \c __len__ attribute, otherwise
00041   //!       a \c ValueError will be raised.
00042   unsigned int size() const {
00043     unsigned int res=0;
00044     try {
00045       res = python::extract<int>(d_seq.attr("__len__")());
00046     } catch (...) {
00047       throw_value_error("sequence does not support length query");
00048     }
00049     return res;
00050   };
00051 
00052   // --------------------------------------------------
00053   //! \brief Returns an element of the sequence
00054   //!
00055   //! ARGUMENTS:
00056   //!   - which: an integer specifying which element should be returned. 
00057   //!  
00058   //! NOTES:
00059   //!   - if the sequence is not \a which elements long, we raise an
00060   //!     \c IndexError
00061   //!   - if the element cannot be converted to type \c T, we raise a
00062   //!     \c ValueError
00063   T operator[](unsigned int which) const {
00064     if(which > size()){
00065       throw_index_error(which);
00066     }
00067 
00068     try{
00069       T res = python::extract<T>(d_seq[which]);
00070       return res;
00071     } catch (...) {
00072       throw_value_error("cannot extract desired type from sequence");
00073     }
00074 
00075     POSTCONDITION(0,"cannot reach this point");
00076     return static_cast<T>(0);
00077   };
00078 private:
00079   python::object d_seq;
00080 };
00081 
00082 
00083 #endif