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