1 /*  $Id: pythonpp_seq.hpp 442490 2014-08-04 18:08:15Z ucko $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Sikorskiy
27 *
28 * File Description: Tiny Python API wrappers
29 *
30 * Status: *Initial*
31 *
32 * ===========================================================================
33 */
34 
35 #ifndef PYTHONPP_SEQ_H
36 #define PYTHONPP_SEQ_H
37 
38 #include "pythonpp_object.hpp"
39 
40 BEGIN_NCBI_SCOPE
41 
42 namespace pythonpp
43 {
44 
45 template<class T> class CSequnceHelper;
46 
47 template<class T>
48 class CSequnceProxy
49 {
50 protected:
51     CSequnceHelper<T>& s;   //< the sequence
52     int offset;             //< item number
53     T value;                //< value
54 
55 public:
56 
CSequnceProxy(CSequnceHelper<T> & seq,int j)57     CSequnceProxy (CSequnceHelper<T>& seq, int j)
58     : s(seq), offset(j), value (s.GetItem(j))
59     {
60     }
61 
CSequnceProxy(const CSequnceProxy<T> & range)62     CSequnceProxy (const CSequnceProxy<T>& range)
63     : s(range.s), offset(range.offset), value(range.value)
64     {
65     }
66 
CSequnceProxy(CObject & obj)67     CSequnceProxy (CObject& obj)
68     : s(dynamic_cast< CSequnceHelper<T>&>(obj))
69     , offset(0)
70     , value(s.getItem(offset))
71     {
72     }
73 
~CSequnceProxy(void)74     ~CSequnceProxy(void)
75     {
76     }
77 
operator const T&(void) const78     operator const T&(void) const
79     {
80         return value;
81     }
82 
operator T&(void)83     operator T&(void)
84     {
85         return value;
86     }
87 
operator =(const CSequnceProxy<T> & rhs)88     CSequnceProxy<T>& operator=(const CSequnceProxy<T>& rhs)
89     {
90         value = rhs.value;
91         s.SetItem(offset, value);
92         return *this;
93     }
94 
operator =(const T & obj)95     CSequnceProxy<T>& operator=(const T& obj)
96     {
97         value = obj;
98         s.SetItem(offset, value);
99         return *this;
100     }
101 
102 }; // end of CSequnceProxy
103 
104 
105 template<class T>
106 class CSequnceHelper : public CObject
107 {
108 public:
109     typedef size_t size_type;
110     typedef CSequnceProxy<T> reference;
111     typedef T const_reference;
112     typedef CSequnceProxy<T>* pointer;
113     typedef int difference_type;
114     typedef T value_type;
115 
116 public:
117 //        virtual size_type max_size() const
118 //        {
119 //            return std::string::npos; // ?
120 //        }
121 
122 //        virtual size_type capacity() const
123 //        {
124 //            return size();
125 //        }
126 
127 //        virtual void swap(CSequnceHelper<T>& c)
128 //        {
129 //            CSequnceHelper<T> temp = c;
130 //            c = ptr();
131 //            set(temp.ptr());
132 //        }
133 
134     // Function name made STL compatible ...
135     // !!! Temporary hack. This function should not be virdual. 1/12/2005 2:43PM ...
size() const136     virtual size_type size () const
137     {
138         return PySequence_Length (Get());
139     }
140 
141 public:
142         /// ???
143 //        explicit CSequnceHelper<T> ()
144 //            :Object(PyTuple_New(0), true)
145 //        {
146 //            validate();
147 //        }
148 
CSequnceHelper(PyObject * obj,EOwnership ownership=eAcquireOwnership)149     CSequnceHelper(PyObject* obj, EOwnership ownership = eAcquireOwnership)
150     : CObject(obj, ownership)
151     {
152         // !!! Somebody should do a type-check here !!!
153     }
154 
CSequnceHelper(const CObject & obj)155     CSequnceHelper (const CObject& obj)
156     : CObject(obj)
157     {
158         // !!! Somebody should do a type-check here !!!
159     }
160 
161     // Assignment acquires new ownership of pointer
162 
operator =(const CObject & rhs)163     CSequnceHelper& operator= (const CObject& rhs)
164     {
165         return (*this = *rhs);
166     }
~CSequnceHelper(void)167     virtual ~CSequnceHelper(void)
168     {
169     }
170 
171 //        CSequnceHelper<T>& operator= (PyObject* obj)
172 //        {
173 //            if ( Get() != obj) {
174 //                Set (obj);
175 //            }
176 //            return *this;
177 //        }
178 
GetLength(void) const179     size_type GetLength (void) const
180     {
181         return PySequence_Length (Get());
182     }
183 
184     // Element access
operator [](int index) const185     const T operator[] (int index) const
186     {
187         return GetItem(index);
188     }
189 
operator [](int index)190     CSequnceProxy<T> operator [] (int index)
191     {
192         return CSequnceProxy<T>(*this, index);
193     }
194 
GetItem(int i) const195     T GetItem (int i) const
196     {
197         PyObject* obj = PySequence_GetItem (Get(), i);
198         if (obj == NULL) {
199             CError::Check();
200         }
201         return T(obj, eTakeOwnership);
202     }
203 
204     // !!! Temporary hack. This function should not be virdual. 1/12/2005 2:39PM ...
SetItem(int i,const T & obj)205     virtual void SetItem (int i, const T& obj)
206     {
207         if (PySequence_SetItem (Get(), i, obj) == -1)
208         {
209             throw CSystemError("Cannot set item with a sequence");
210         }
211         IncRefCount(obj);
212     }
213 
Repeat(int count) const214     CSequnceHelper<T> Repeat (int count) const
215     {
216         return CSequnceHelper<T> (PySequence_Repeat (Get(), count), eTakeOwnership);
217     }
218 
Concat(const CSequnceHelper<T> & other) const219     CSequnceHelper<T> Concat (const CSequnceHelper<T>& other) const
220     {
221         return CSequnceHelper<T> (PySequence_Concat(Get(), *other), eTakeOwnership);
222     }
223 
224     // more STL compatability
front(void) const225     const T front (void) const
226     {
227         return GetItem(0);
228     }
229 
front(void)230     CSequnceProxy<T> front(void)
231     {
232         return CSequnceProxy<T>(this, 0);
233     }
234 
back(void) const235     const T back (void) const
236     {
237         return GetItem(size() - 1);
238     }
239 
back(void)240     CSequnceProxy<T> back(void)
241     {
242         return CSequnceProxy<T>(this, size() - 1);
243     }
244 
VerifyLength(size_type required_size) const245     void VerifyLength(size_type required_size) const
246     {
247         if ( size() != required_size )
248         {
249             throw CIndexError ("Unexpected CSequnceHelper<T> length.");
250         }
251     }
252 
VerifyLength(size_type min_size,size_type max_size) const253     void VerifyLength(size_type min_size, size_type max_size) const
254     {
255         size_type n = size();
256         if (n < min_size || n > max_size)
257         {
258             throw CIndexError ("Unexpected CSequnceHelper<T> length.");
259         }
260     }
261 
262 public:
HasSameType(PyObject * obj)263     static bool HasSameType(PyObject* obj)
264     {
265         return PySequence_Check (obj) == 1;
266     }
267 
268 public:
269     // Iterators ...
270 
271     class iterator
272     // : public std::iterator<std::random_access_iterator_tag, CSequnceProxy<T>, int>
273     {
274     protected:
275         friend class CSequnceHelper<T>;
276         CSequnceHelper<T>* seq;
277         int position;
278 
279     public:
~iterator(void)280         ~iterator (void)
281         {
282         }
283 
iterator(void)284         iterator (void)
285         : seq( 0 )
286         , position( 0 )
287         {
288         }
289 
iterator(CSequnceHelper<T> * s,int where)290         iterator (CSequnceHelper<T>* s, int where)
291         : seq( s )
292         , position( where )
293         {
294         }
295 
iterator(const iterator & other)296         iterator (const iterator& other)
297         : seq( other.seq )
298         , position( other.position )
299         {
300         }
301 
eql(const iterator & other) const302         bool eql (const iterator& other) const
303         {
304             return (*seq == *other.seq) && (position == other.position);
305         }
306 
neq(const iterator & other) const307         bool neq (const iterator& other) const
308         {
309             return (*seq != *other.seq) || (position != other.position);
310         }
311 
lss(const iterator & other) const312         bool lss (const iterator& other) const
313         {
314             return (position < other.position);
315         }
316 
gtr(const iterator & other) const317         bool gtr (const iterator& other) const
318         {
319             return (position > other.position);
320         }
321 
leq(const iterator & other) const322         bool leq (const iterator& other) const
323         {
324             return (position <= other.position);
325         }
326 
geq(const iterator & other) const327         bool geq (const iterator& other) const
328         {
329             return (position >= other.position);
330         }
331 
operator *(void)332         CSequnceProxy<T> operator*(void)
333         {
334             return CSequnceProxy<T>(*seq, position);
335         }
336 
operator [](int i)337         CSequnceProxy<T> operator[] (int i)
338         {
339             return CSequnceProxy<T>(*seq, position + i);
340         }
341 
operator =(const iterator & other)342         iterator& operator=(const iterator& other)
343         {
344             if ( this != &other ) {
345                 seq = other.seq;
346                 position = other.position;
347             }
348             return *this;
349         }
350 
operator +(int n) const351         iterator operator+(int n) const
352         {
353             return iterator(seq, position + n);
354         }
355 
operator -(int n) const356         iterator operator-(int n) const
357         {
358             return iterator(seq, position - n);
359         }
360 
operator +=(int n)361         iterator& operator+=(int n)
362         {
363             position = position + n;
364             return *this;
365         }
366 
operator -=(int n)367         iterator& operator-=(int n)
368         {
369             position = position - n;
370             return *this;
371         }
372 
operator -(const iterator & other) const373         int operator-(const iterator& other) const
374         {
375             if (*seq != *other.seq) {
376                 throw CSystemError("CSequnceHelper<T>::iterator comparison error");
377             }
378             return position - other.position;
379         }
380 
381         // prefix ++
operator ++(void)382         iterator& operator++ (void)
383         {
384             ++position;
385             return *this;
386         }
387         // postfix ++
operator ++(int)388         iterator operator++ (int)
389         {
390             return iterator(seq, position++);
391         }
392         // prefix --
operator --(void)393         iterator& operator-- (void)
394         {
395             --position;
396             return *this;
397         }
398         // postfix --
operator --(int)399         iterator operator-- (int)
400         {
401             return iterator(seq, position--);
402         }
403     };    // end of class CSequnceHelper<T>::iterator
404 
begin(void)405     iterator begin (void)
406     {
407         return iterator(this, 0);
408     }
409 
end(void)410     iterator end (void)
411     {
412         return iterator(this, GetLength());
413     }
414 
415     class const_iterator // : public std::iterator<std::random_access_iterator_tag, CObject, int>
416     {
417     protected:
418         friend class CSequnceHelper<T>;
419         const CSequnceHelper<T>* seq;
420         int position;
421 
422     public:
~const_iterator(void)423         ~const_iterator (void)
424         {
425         }
426 
const_iterator(void)427         const_iterator (void)
428         : seq( 0 )
429         , position( 0 )
430         {
431         }
432 
const_iterator(const CSequnceHelper<T> * s,int where)433         const_iterator (const CSequnceHelper<T>* s, int where)
434         : seq( s )
435         , position( where )
436         {
437         }
438 
const_iterator(const const_iterator & other)439         const_iterator(const const_iterator& other)
440         : seq( other.seq )
441         , position( other.position )
442         {
443         }
444 
operator *(void) const445         const T operator*(void) const
446         {
447             return seq->GetItem(position);
448         }
449 
operator [](int i) const450         const T operator[] (int i) const
451         {
452             return seq->GetItem(position + i);
453         }
454 
operator =(const const_iterator & other)455         const_iterator& operator=(const const_iterator& other)
456         {
457             if ( this != &other ) {
458                 seq = other.seq;
459                 position = other.position;
460             }
461             return *this;
462         }
463 
operator +(int n) const464         const_iterator operator+(int n) const
465         {
466             return const_iterator(seq, position + n);
467         }
468 
operator ==(const const_iterator & other) const469         bool operator == (const const_iterator& other) const
470         {
471             return (*seq == *other.seq) && (position == other.position);
472         }
473 
operator !=(const const_iterator & other) const474         bool operator != (const const_iterator& other) const
475         {
476             return (*seq != *other.seq) || (position != other.position);
477         }
478 
lss(const const_iterator & other) const479         bool lss (const const_iterator& other) const
480         {
481             return (position < other.position);
482         }
483 
gtr(const const_iterator & other) const484         bool gtr (const const_iterator& other) const
485         {
486             return (position > other.position);
487         }
488 
leq(const const_iterator & other) const489         bool leq (const const_iterator& other) const
490         {
491             return (position <= other.position);
492         }
493 
geq(const const_iterator & other) const494         bool geq (const const_iterator& other) const
495         {
496             return (position >= other.position);
497         }
498 
operator -(int n)499         const_iterator operator-(int n)
500         {
501             return const_iterator(seq, position - n);
502         }
503 
operator +=(int n)504         const_iterator& operator+=(int n)
505         {
506             position = position + n;
507             return *this;
508         }
509 
operator -=(int n)510         const_iterator& operator-=(int n)
511         {
512             position = position - n;
513             return *this;
514         }
515 
operator -(const const_iterator & other) const516         int operator-(const const_iterator& other) const
517         {
518             if (*seq != *other.seq) {
519                 throw CRuntimeError ("CSequnceHelper<T>::const_iterator::- error");
520             }
521             return position - other.position;
522         }
523 
524         // prefix ++
operator ++(void)525         const_iterator& operator++ (void)
526         {
527             ++position;
528             return *this;
529         }
530         // postfix ++
operator ++(int)531         const_iterator operator++ (int)
532         {
533             return const_iterator(seq, position++);
534         }
535         // prefix --
operator --()536         const_iterator& operator-- ()
537         {
538             --position;
539             return *this;
540         }
541         // postfix --
operator --(int)542         const_iterator operator-- (int)
543         {
544             return const_iterator(seq, position--);
545         }
546     };    // end of class CSequnceHelper<T>::const_iterator
547 
begin(void) const548     const_iterator begin (void) const
549     {
550         return const_iterator(this, 0);
551     }
552 
end(void) const553     const_iterator end (void) const
554     {
555         return const_iterator(this, GetLength());
556     }
557 };
558 
559 typedef CSequnceHelper<CObject> CSequence;
560 
561 class CList;
562 
563 // PyTuple_Type
564 class CTuple : public CSequence
565 {
566 //PyAPI_FUNC(CInt) _PyTuple_Resize(PyObject **, int);
567 //PyAPI_FUNC(PyObject *) PyTuple_Pack(CInt, ...);
568 // int PyTuple_GET_SIZE(   PyObject *p)
569 // PyObject* PyTuple_GET_ITEM( PyObject *p, int pos)
570 // void PyTuple_SET_ITEM(  PyObject *p, int pos, PyObject *o)
571 
572 public:
CTuple(PyObject * obj,EOwnership ownership=eAcquireOwnership)573     CTuple(PyObject* obj, EOwnership ownership = eAcquireOwnership)
574     : CSequence(obj, ownership)
575     {
576         if ( !HasExactSameType(obj) ) {
577             throw CTypeError("Invalid conversion");
578         }
579     }
CTuple(const CObject & obj)580     CTuple(const CObject& obj)
581     : CSequence(obj)
582     {
583         if ( !HasExactSameType(obj) ) {
584             throw CTypeError("Invalid conversion");
585         }
586     }
CTuple(const CTuple & obj)587     CTuple(const CTuple& obj)
588     : CSequence(obj)
589     {
590     }
591     CTuple(const CList& obj);
592     /// Create a CTuple of size "size" and initialize it with python None
CTuple(size_t size=0)593     CTuple(size_t size = 0)
594     : CSequence(PyTuple_New (size), eTakeOwnership)
595     {
596         // *** WARNING *** PyTuple_SetItem does not increment the new item's reference
597         // count, but does decrement the reference count of the item it replaces,
598         // if not nil.  It does *decrement* the reference count if it is *not*
599         // inserted in the tuple.
600 
601         for ( size_t i = 0; i < size; ++i ) {
602             if ( PyTuple_SetItem (Get(), i, Py_None) == -1 ) {
603                 IncRefCount(Py_None);
604                 throw CSystemError("PyTuple_SetItem error");
605             }
606             IncRefCount(Py_None);
607         }
608     }
609 
610 public:
611     // Assign operators ...
operator =(const CObject & obj)612     CTuple& operator= (const CObject& obj)
613     {
614         if ( this != &obj ) {
615             if ( !HasExactSameType(obj) ) {
616                 throw CTypeError("Invalid conversion");
617             }
618             Set(obj);
619         }
620         return *this;
621     }
operator =(PyObject * obj)622     CTuple& operator= (PyObject* obj)
623     {
624         if ( Get() != obj ) {
625             if ( !HasExactSameType(obj) ) {
626                 throw CTypeError("Invalid conversion");
627             }
628             Set(obj);
629         }
630         return *this;
631     }
632 
633 public:
SetItem(int offset,const CObject & obj)634     void SetItem (int offset, const CObject& obj)
635     {
636         // PyTuple_SetItem does not increment the new item's reference
637         // count, but does decrement the reference count of the item it
638         // replaces.
639         // It does *decrement* the reference count if it is *not*
640         // inserted in the tuple.
641 
642         if ( PyTuple_SetItem (Get(), offset, obj) == -1 ) {
643             IncRefCount(obj);
644             throw CSystemError("");
645         }
646         IncRefCount(obj);
647     }
GetItem(int offset)648     CObject GetItem(int offset)
649     {
650         PyObject* obj = PyTuple_GetItem(Get(), offset);
651         if ( !obj ) {
652             throw CSystemError("");
653         }
654         return CObject(obj);
655     }
656 
657     // Fast version. Acquires ownership of obj ...
SetItemFast(int offset,PyObject * obj)658     void SetItemFast (int offset, PyObject* obj)
659     {
660         if(PyTuple_SetItem (Get(), offset, obj) == -1 ) {
661             IncRefCount(obj);
662             throw CSystemError("");
663         }
664     }
665     // Fast version. Does not increment a counter ...
GetItemFast(int offset)666     PyObject* GetItemFast(int offset)
667     {
668         return PyTuple_GetItem(Get(), offset);
669     }
670 
GetSlice(int i,int j) const671     CTuple GetSlice (int i, int j) const
672     {
673         return CTuple(PyTuple_GetSlice(Get(), i, j), eTakeOwnership);
674     }
size(void) const675     size_type size(void) const
676     {
677         return PyTuple_Size(Get());
678     }
679 
680 public:
HasExactSameType(PyObject * obj)681     static bool HasExactSameType(PyObject* obj)
682     {
683         return PyTuple_CheckExact(obj);
684     }
HasSameType(PyObject * obj)685     static bool HasSameType(PyObject* obj)
686     {
687         return PyTuple_Check (obj);
688     }
689 };
690 
691 // PyList_Type
692 class CList : public CSequence
693 {
694 // PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *);
695 // int PyList_GET_SIZE(    PyObject *list)
696 // PyObject* PyList_GET_ITEM(  PyObject *list, int i)
697 // void PyList_SET_ITEM(   PyObject *list, int i, PyObject *o)
698 
699 public:
CList(PyObject * obj,EOwnership ownership=eAcquireOwnership)700     CList(PyObject* obj, EOwnership ownership = eAcquireOwnership)
701     : CSequence(obj, ownership)
702     {
703         if ( !HasExactSameType(obj) ) {
704             throw CTypeError("Invalid conversion");
705         }
706     }
CList(const CObject & obj)707     CList(const CObject& obj)
708     : CSequence(obj)
709     {
710         if ( !HasExactSameType(obj) ) {
711             throw CTypeError("Invalid conversion");
712         }
713     }
CList(const CList & obj)714     CList(const CList& obj)
715     : CSequence(obj)
716     {
717     }
718     /// Create a CTuple of size "size" and initialize it with python None
CList(size_t size=0)719     CList(size_t size = 0)
720     : CSequence(PyList_New (size), eTakeOwnership)
721     {
722         for ( size_t i = 0; i < size; ++i ) {
723             if ( PyList_SetItem (Get(), i, Py_None) != 0 ) {
724                 throw CSystemError("");
725             }
726             IncRefCount(Py_None);
727         }
728     }
729 
730 public:
731     // Assign operators ...
operator =(const CObject & obj)732     CList& operator= (const CObject& obj)
733     {
734         if ( this != &obj ) {
735             if ( !HasExactSameType(obj) ) {
736                 throw CTypeError("Invalid conversion");
737             }
738             Set(obj);
739         }
740         return *this;
741     }
operator =(PyObject * obj)742     CList& operator= (PyObject* obj)
743     {
744         if ( Get() != obj ) {
745             if ( !HasExactSameType(obj) ) {
746                 throw CTypeError("Invalid conversion");
747             }
748             Set(obj);
749         }
750         return *this;
751     }
752 
753 public:
SetItem(int offset,const CObject & obj)754     void SetItem (int offset, const CObject& obj)
755     {
756         // PyList_SetItem does not increment the new item's reference
757         // count, but does decrement the reference count of the item it replaces,
758         // if not nil.  It does *decrement* the reference count if it is *not*
759         // inserted in the list.
760 
761         if ( PyList_SetItem (Get(), offset, obj) == -1 ) {
762             IncRefCount(obj);
763             throw CSystemError("");
764         }
765         IncRefCount(obj);
766     }
GetItem(int offset)767     CObject GetItem(int offset)
768     {
769         PyObject* obj = PyList_GetItem(Get(), offset);
770         if ( !obj ) {
771             throw CSystemError("");
772         }
773         return CObject(obj);
774     }
775 
776     // Fast version. Acquires ownership of obj ...
SetItemFast(int offset,PyObject * obj)777     void SetItemFast (int offset, PyObject* obj)
778     {
779         if(PyList_SetItem (Get(), offset, obj) != 0) {
780             throw CSystemError("");
781         }
782     }
783     // Fast version. Does not increment a counter ...
GetItemFast(int offset)784     PyObject* GetItemFast(int offset)
785     {
786         return PyList_GetItem(Get(), offset);
787     }
788 
789 public:
GetSlice(int i,int j) const790     CList GetSlice (int i, int j) const
791     {
792         return CList (PyList_GetSlice (Get(), i, j), eTakeOwnership);
793     }
SetSlice(int i,int j,const CObject & obj)794     void SetSlice (int i, int j, const CObject& obj)
795     {
796         if(PyList_SetSlice (Get(), i, j, obj) != 0) {
797             throw CSystemError("");
798         }
799     }
800 
801 public:
Append(const CObject & obj)802     void Append (const CObject& obj)
803     {
804         Append(obj.Get());
805     }
Append(PyObject * obj)806     void Append (PyObject* obj)
807     {
808         if(PyList_Append (Get(), obj) == -1) {
809             throw CSystemError("");
810         }
811     }
Insert(int i,const CObject & obj)812     void Insert (int i, const CObject& obj)
813     {
814         if(PyList_Insert (Get(), i, obj) == -1) {
815             throw CSystemError("");
816         }
817     }
Sort(void)818     void Sort (void)
819     {
820         if(PyList_Sort(Get()) == -1) {
821             throw CSystemError("");
822         }
823     }
Reverse(void)824     void Reverse (void)
825     {
826         if(PyList_Reverse(Get()) == -1) {
827             throw CSystemError("");
828         }
829     }
830 
Clear(void)831     void Clear (void)
832     {
833         Set(PyList_New(0));
834         IncRefCount(Get());
835     }
836 
837 public:
838     // Function name is made STL compatible ...
size(void) const839     size_type size(void) const
840     {
841         return PyList_Size(Get());
842     }
843 
844 public:
HasExactSameType(PyObject * obj)845     static bool HasExactSameType(PyObject* obj)
846     {
847         return PyList_CheckExact (obj);
848     }
HasSameType(PyObject * obj)849     static bool HasSameType(PyObject* obj)
850     {
851         return PyList_Check (obj);
852     }
853 };
854 
855 #if PY_VERSION_HEX >= 0x02040000
856 // PySet_Type
857 class CSet : public CObject
858 {
859 public:
860 public:
HasSameType(PyObject * obj)861     static bool HasSameType(PyObject* obj)
862     {
863         return PyAnySet_Check(obj);
864     }
HasExactSameType(PyObject * obj)865     static bool HasExactSameType(PyObject* obj)
866     {
867         return PyAnySet_Check(obj);
868     }
869 };
870 
871 // PyFrozenSet_Type
872 class CFrozenSet : public CObject
873 {
874 public:
875 public:
HasSameType(PyObject * obj)876     static bool HasSameType(PyObject* obj)
877     {
878         return PyAnySet_Check(obj);
879     }
HasExactSameType(PyObject * obj)880     static bool HasExactSameType(PyObject* obj)
881     {
882         return PyFrozenSet_CheckExact(obj);
883     }
884 };
885 #endif
886 
887 //////////////////////////////////////////////////////////////////////////
888 inline
CTuple(const CList & obj)889 CTuple::CTuple(const CList& obj)
890 : CSequence(PyList_AsTuple(obj), eTakeOwnership)
891 {
892 }
893 
894 }                                       // namespace pythonpp
895 
896 END_NCBI_SCOPE
897 
898 #endif                                  // PYTHONPP_SEQ_H
899 
900