Py11  v0.2
This is a minimalist Python wrapper for C++11.
py.hpp
1 #ifndef PY11_PY_HPP
2 #define PY11_PY_HPP
3 
4 #include <Python.h>
5 #include <iostream>
6 #include <exception>
7 #include <stdexcept>
8 #include <initializer_list>
9 #include <limits>
10 
11 #ifndef PY11_ENFORCE
12 #define PY11_ENFORCE 1
13 #endif
14 
15 #include "_err.hpp"
16 
17 namespace py {
18 
19 /* assistant classes
20 *******************/
21 
22 class iter;
23 
24 class PPyObject {
25 private:
26  PyObject* _p;
27 public:
28  PPyObject(PyObject* p):_p(p)
29  {}
30 
31  operator PyObject*()const
32  {
33  return _p;
34  }
35 
36  template<typename T> explicit operator T()const
37  {
38  return (T)_p;
39  }
40 };
41 
42 namespace details{
43  class py_initer{
44  public:
45  py_initer()
46  {
47  //std::cout << ">>>>> init" << std::endl;
48  Py_Initialize();
49  }
50 
51  ~py_initer()
52  {
53  Py_Finalize();
54  //std::cout << ">>>>> fini" << std::endl;
55  }
56  };
57 
58  class py_initer_wrap{
59  public:
60  py_initer_wrap()
61  {
62  static py_initer __init;
63  }
64  };
65 };
66 
67 /** wrapper of PyObject.
68  */
69 class obj : private details::py_initer_wrap{
70 friend class tuple;
71 friend class list;
72 friend class set;
73 
74 protected:
75 
76  PyObject* _p;
77 
78  void __reset()const
79  {
80  // only for stolen references
81  const_cast<obj&>(*this)._p = NULL;
82  }
83 
84  void enter(PyObject* p)noexcept
85  {
86  _p = p;
87  __enter();
88  }
89 
90  void __enter()noexcept
91  {
92  if(_p)
93  Py_INCREF(_p);
94  }
95 
96 private:
97  /** disabled.
98  * to prohibit getting a PyObject* from p() without correct ref counting
99  */
100  obj(PPyObject p);
101 
102 public:
103  obj()noexcept:_p(NULL)
104  {}
105 
106 
107  /** copy ctor.
108  */
109  obj(const obj& o)noexcept:_p(o._p)
110  {
111  __enter();
112  }
113 
114  obj(obj& o):_p(o._p)
115  {
116  __enter();
117  }
118 
119  obj& operator=(const obj& o)
120  {
121  if(o._p!=_p){
122  release();
123  enter(o._p);
124  }
125  return *this;
126  }
127 
128  /** create from Py functions.
129  * in most of cases, need not to inc ref.
130  * please read python doc carefully
131  */
132  obj(PyObject* p, bool borrowed = false)noexcept:_p(p)
133  {
134  if(borrowed)
135  Py_XINCREF(_p);
136  }
137 
138  obj& operator=(PyObject* p)noexcept
139  {
140  if(p!=_p){
141  release();
142  _p = p;
143  }
144  return *this;
145  }
146 
147  /** move ctor.
148  */
149  obj(obj&& o)noexcept:_p(o._p)
150  {
151  o._p = NULL;
152  }
153 
154  obj& operator=(obj&& o)noexcept
155  {
156  if(o._p!=_p){
157  release();
158  _p = o.transfer();
159  }
160  return *this;
161  }
162 
163 
164  /** tuple.
165  */
166  obj(std::initializer_list<obj> l):_p(PyTuple_New(l.size()))
167  {
168  long i = 0;
169  for(auto &x: l){
170  PyTuple_SET_ITEM(_p, i++, x._p);
171  x.__reset();
172  }
173  }
174 
175  obj& operator = (std::initializer_list<obj> l)
176  {
177  _p = PyTuple_New(l.size());
178  long i = 0;
179  for(auto &x: l){
180  PyTuple_SET_ITEM(_p, i++, x._p);
181  x.__reset();
182  }
183  return *this;
184  }
185 
186  /** dtor.
187  */
188  ~obj()noexcept
189  {
190  release();
191  }
192 
193  /** release the contained object
194  */
195  void release()noexcept
196  {
197  if(_p){
198  Py_DECREF(_p);
199  _p = NULL;
200  }
201  }
202 
203  /** transfer the ownership of inner object.
204  * @return the current PyObject*
205  */
206  PyObject* transfer()noexcept
207  {
208  PyObject* r = _p;
209  if(_p){
210  _p = NULL;
211  }
212  return r;
213  }
214 
215  /** test null.
216  */
217  bool operator !()const
218  {
219  return !_p;
220  }
221 
222  // cast
223 
224  /**
225  */
226  bool py_not()const
227  {
228  return (!_p) || PyObject_Not(_p);
229  }
230 
231  /** int.
232  */
233  obj(int i):_p(PyInt_FromLong(i))
234  {}
235 
236  /** long.
237  */
238  obj(long i):_p(PyInt_FromLong(i))
239  {}
240 
241  /** is_int.
242  */
243  bool is_int()const
244  {
245  return _p && PyInt_Check(_p);
246  }
247 
248  /** get long from obj
249  * @throw type_err
250  */
251  long as_long()const
252  {
253  long r = PyInt_AsLong(_p);
254  if(r== -1 && PyErr_Occurred() != NULL){
255  throw type_err("as_long failed");
256  }
257  return r;
258  }
259 
260  /** double ctor.
261  */
262  obj(double v):_p(PyFloat_FromDouble(v))
263  {}
264 
265  /** is_float.
266  */
267  bool is_float()const
268  {
269  return _p && PyFloat_Check(_p);
270  }
271 
272  /** as_double from obj.
273  * @throw type_err
274  */
275  double as_double()const
276  {
277  double r = PyFloat_AsDouble(_p);
278  if(r== -1.0 && PyErr_Occurred() != NULL){
279  throw type_err("as_double failed");
280  }
281  return r;
282  }
283 
284  /** str.
285  */
286  obj(const char* s):_p(PyString_FromString(s))
287  {}
288 
289  /** c_str().
290  * @throw type_err
291  */
292  const char* c_str()const
293  {
294  const char* p;
295  if(PyString_Check(_p)){
296  p = PyString_AsString(_p);
297  }
298  else if(PyUnicode_Check(_p)){
299  p = PyUnicode_AS_DATA(_p);
300  }
301  else if(PyByteArray_Check(_p)){
302  p = PyByteArray_AsString(_p);
303  }
304  else
305  throw type_err("c_str failed");
306  return p;
307  }
308 
309  /** py object type.
310  * @throw type_err
311  */
312  obj type()const
313  {
314  if(_p){
315  PyObject* p = PyObject_Type(_p);
316  if(!p)
317  throw type_err("type failed");
318  return p;
319  }
320  return obj();
321  }
322 
323  /** type check
324  * @throw type_err
325  * @throw val_err
326  */
327  bool is_a(const obj& t)const
328  {
329  if(!t)
330  throw type_err("is_a with null type");
331 
332  int r = PyObject_TypeCheck(_p, t._p->ob_type);
333  if(r == -1)
334  throw val_err("is_a failed");
335 
336  return r;
337  }
338 
339  // attr
340 
341  /** has attr.
342  */
343  bool has_attr(const obj& o)const
344  {
345  return PyObject_HasAttr(_p, o._p);
346  }
347 
348  /** has attr.
349  */
350  bool has_attr(const char* s)const
351  {
352  return PyObject_HasAttrString(_p, s);
353  }
354 
355  /** get attr.
356  * @throw index_err
357  */
358  obj attr(const obj& o)const
359  {
360  PyObject* p = PyObject_GetAttr(_p, o._p);
361  if(!p){
362  throw index_err("non-existing attr");
363  }
364  return p;
365  }
366 
367  /** get attr.
368  * @throw index_err
369  */
370  obj attr(const char* s)const
371  {
372  PyObject* p = PyObject_GetAttrString(_p, s);
373  if(!p){
374  throw index_err("non-existing attr");
375  }
376  return p;
377  }
378 
379  /** get attr, short form.
380  * @throw index_err
381  */
382  obj a(const char* s)const
383  {
384  PyObject* p = PyObject_GetAttrString(_p, s);
385  if(!p){
386  throw index_err("non-existing attr");
387  }
388  return p;
389  }
390 
391  /** set attr.
392  * @throw index_err
393  */
394  void set_attr(const obj& a, const obj& v)
395  {
396  int r = PyObject_SetAttr(_p, a._p, v._p);
397  if(r == -1)
398  throw index_err("set_attr failed");
399  }
400 
401  /** set attr.
402  * @throw index_err
403  */
404  void set_attr(const char* a, const obj& v)
405  {
406  int r = PyObject_SetAttrString(_p, a, v._p);
407  if(r == -1)
408  throw index_err("set_attr failed");
409  }
410 
411  /** del attr.
412  * @throw index_err
413  */
414  void del_attr(const obj& a)
415  {
416  int r = PyObject_DelAttr(_p, a._p);
417  if(r == -1)
418  throw index_err("del_attr failed");
419  }
420 
421  /** del attr.
422  * @throw index_err
423  */
424  void del_attr(const char* a)
425  {
426  int r = PyObject_DelAttrString(_p, a);
427  if(r == -1)
428  throw index_err("del_attr failed");
429  }
430 
431  // comparison
432 
433  /** <
434  * @throw val_err
435  */
436  bool operator < (const obj& o)const
437  {
438  if(_p == o._p)
439  return false;
440  if(_p == NULL)
441  return true;
442  if(o._p == NULL)
443  return false;
444  int r = PyObject_RichCompareBool(_p, o._p, Py_LT);
445  if(r == -1){
446  throw val_err("op < failed");
447  }
448  return r;
449  }
450 
451  bool operator <= (const obj& o)const
452  {
453  if(_p == o._p)
454  return true;
455  if(_p == NULL)
456  return true;
457  if(o._p == NULL)
458  return false;
459  int r = PyObject_RichCompareBool(_p, o._p, Py_LE);
460  if(r == -1){
461  throw val_err("op <= failed");
462  }
463  return r;
464  }
465 
466  bool operator == (const obj& o)const
467  {
468  if(_p == o._p)
469  return true;
470  if(_p == NULL)
471  return false;
472  if(o._p == NULL)
473  return false;
474  int r = PyObject_RichCompareBool(_p, o._p, Py_EQ);
475  if(r == -1){
476  throw val_err("op == failed");
477  }
478  return r;
479  }
480 
481  bool operator != (const obj& o)const
482  {
483  if(_p == o._p)
484  return false;
485  if(_p == NULL)
486  return true;
487  if(o._p == NULL)
488  return true;
489  int r = PyObject_RichCompareBool(_p, o._p, Py_NE);
490  if(r == -1){
491  throw val_err("op != failed");
492  }
493  return r;
494  }
495 
496  bool operator > (const obj& o)const
497  {
498  if(_p == o._p)
499  return false;
500  if(_p == NULL)
501  return false;
502  if(o._p == NULL)
503  return true;
504  int r = PyObject_RichCompareBool(_p, o._p, Py_GT);
505  if(r == -1){
506  throw val_err("op > failed");
507  }
508  return r;
509  }
510 
511  bool operator >= (const obj& o)const
512  {
513  if(_p == o._p)
514  return true;
515  if(_p == NULL)
516  return false;
517  if(o._p == NULL)
518  return true;
519  int r = PyObject_RichCompareBool(_p, o._p, Py_GE);
520  if(r == -1){
521  throw val_err("op >= failed");
522  }
523  return r;
524  }
525 
526  // output
527 
528  /** repr.
529  * @throw val_err
530  */
531  obj repr()const
532  {
533  PyObject* p = PyObject_Repr(_p);
534  if(p == NULL)
535  throw val_err("repr failed");
536  return p;
537  }
538 
539  /** str.
540  * @throw val_err
541  */
542  obj to_str()const
543  {
544  PyObject* p = PyObject_Str(_p);
545  if(p == NULL){
546  throw val_err("str failed");
547  }
548  return p;
549  }
550 
551  /** unicode.
552  * @throw val_err
553  */
555  {
556  PyObject* p = PyObject_Unicode(_p);
557  if(p == NULL)
558  throw val_err("unicode failed");
559  return p;
560  }
561 
562  void output(std::ostream& s)const
563  {
564  if(!_p){
565  s << "<NULL>";
566  return;
567  }
568  if(PyString_Check(_p)){
569  const char* p = PyString_AsString(_p);
570  if(!p)
571  throw val_err("bad internal string");
572  s << p;
573  }
574  else{
575  s << to_str().c_str();
576  }
577  }
578 
579  // call
580 
581  /** test callable.
582  */
583  bool is_callable()const
584  {
585  return (_p) && (PyCallable_Check(_p));
586  }
587 
588  /** call using operator.
589  * @throw type_err
590  */
591  template<typename ...argT>obj operator ()(argT&& ...a)const
592  {
593  PyObject* r = PyObject_CallFunctionObjArgs(_p, obj(a)._p..., NULL);
594  if(r == NULL)
595  throw type_err("operator() failed");
596  return r;
597  }
598 
599  /** call with args.
600  * @throw type_err
601  */
602  obj call(const obj& args)const
603  {
604  PyObject* r = PyObject_CallObject(_p, args._p);
605  if(r == NULL)
606  throw type_err("call failed");
607  return r;
608  }
609 
610  /** call with args, and key/value pairs.
611  * @throw type_err
612  */
613  obj call(const obj& args, const obj& kw)const
614  {
615  PyObject* r = PyObject_Call(_p, args._p, kw._p);
616  if(r == NULL)
617  throw type_err("call failed");
618  return r;
619  }
620 
621  // container methods
622 
623  /** 'len' as 'size'.
624  * @throw type_err
625  */
626  long size()const
627  {
628  if(_p){
629  if(PySequence_Check(_p)){
630  long r = PySequence_Size(_p);
631  if(r != -1)
632  return r;
633  }
634  else if(PyMapping_Check(_p)){
635  long r = PyMapping_Size(_p);
636  if(r != -1)
637  return r;
638  }
639  else if(PyAnySet_Check(_p)){
640  long r = PySet_Size(_p);
641  if(r != -1)
642  return r;
643  }
644  }
645  throw type_err("len failed");
646  }
647 
648  /** 'in' as 'has'.
649  * @throw type_err
650  */
651  bool has(const obj& x)const
652  {
653  if(_p){
654  if(PySequence_Check(_p)){
655  int r = PySequence_Contains(_p, x._p);
656  if(r != -1)
657  return r;
658  }
659  else if(PyMapping_Check(_p)){
660  int r = PyMapping_HasKey(_p, x._p);
661  if(r != -1)
662  return r;
663  }
664  else if(PyAnySet_Check(_p)){
665  int r = PySet_Contains(_p, x._p);
666  if(r != -1)
667  return r;
668  }
669  }
670  throw type_err("has failed");
671  }
672 
673  /** get item.
674  * Warning, a new obj will be got! not a reference to the original one!
675  * @throw index_err
676  */
677  const obj operator [](const obj& o)const
678  {
679  PyObject* p = PyObject_GetItem(_p, o._p);
680  if(!p){
681  throw index_err("non-existing item");
682  }
683  return p;
684  }
685 
686  /** set_item.
687  * @throw index_err
688  */
689  void set_item(const obj& key, const obj& value)
690  {
691  int r = PyObject_SetItem(_p, key._p, value._p);
692  if(r == -1)
693  throw index_err("set_item failed");
694  }
695 
696  /** del_item.
697  * @throw index_err
698  */
699  void del_item(const obj& key)
700  {
701  int r = PyObject_DelItem(_p, key._p);
702  if(r == -1)
703  throw index_err("del_item failed");
704  }
705 
706  /** get the begin iter.
707  * @throw type_err
708  */
709  inline iter begin()const;
710 
711  /** get the end iter.
712  */
713  inline iter end()const;
714 
715  // introspection
716 
717  /** py object dir.
718  * @throw val_err
719  */
720  obj dir()const
721  {
722  PyObject* p = PyObject_Dir(_p);
723  if(!p)
724  throw val_err("dir failed");
725  return p;
726  }
727 
728  /** refcnt.
729  */
730  Py_ssize_t refcnt()const
731  {
732  if(_p)
733  return _p->ob_refcnt;
734  else
735  return 0;
736  }
737 
738  /** get inner PyObject.
739  */
740  PPyObject p()const
741  {
742  return _p;
743  }
744 
745 };
746 
747 
748 /** ostream output
749  */
750 inline std::ostream& operator <<(std::ostream& s, const obj& o)
751 {
752  o.output(s);
753  return s;
754 }
755 
756 }; //ns py
757 
758 /* sub types
759 ***********/
760 
761 #include "_iter.hpp"
762 
763 #include "_seq.hpp"
764 #include "_tuple.hpp"
765 #include "_list.hpp"
766 #include "_str.hpp"
767 
768 #include "_file.hpp"
769 
770 #include "_num.hpp"
771 #include "_set.hpp"
772 
773 #include "_dict.hpp"
774 
775 /* implementation
776 ****************/
777 
778 #include "_sys.hpp"
779 
780 namespace py {
781 
782 inline iter obj::end()const
783 {
784  return iter();
785 }
786 
787 inline iter obj::begin()const
788 {
789  return iter(*this);
790 }
791 
792 inline list seq::to_list()const
793 {
794  PyObject* r = PySequence_List(_p);
795  if(r)
796  return r;
797  throw type_err("to_list failed");
798 }
799 
800 inline tuple seq::to_tuple()const
801 {
802  PyObject* r = PySequence_Tuple(_p);
803  if(r)
804  return r;
805  throw type_err("to_tuple failed");
806 }
807 
808 }; // ns py
809 
810 #endif // PY11_PY_HPP
obj call(const obj &args, const obj &kw) const
call with args, and key/value pairs.
Definition: py.hpp:613
obj(int i)
int.
Definition: py.hpp:233
void set_attr(const char *a, const obj &v)
set attr.
Definition: py.hpp:404
obj(const obj &o) noexcept
copy ctor.
Definition: py.hpp:109
bool operator!() const
test null.
Definition: py.hpp:217
Py_ssize_t refcnt() const
refcnt.
Definition: py.hpp:730
obj(obj &&o) noexcept
move ctor.
Definition: py.hpp:149
obj(PyObject *p, bool borrowed=false) noexcept
create from Py functions.
Definition: py.hpp:132
void del_item(const obj &key)
del_item.
Definition: py.hpp:699
bool is_a(const obj &t) const
type check
Definition: py.hpp:327
void set_item(const obj &key, const obj &value)
set_item.
Definition: py.hpp:689
wrapper of PyObject.
Definition: py.hpp:69
void del_attr(const char *a)
del attr.
Definition: py.hpp:424
double as_double() const
as_double from obj.
Definition: py.hpp:275
obj repr() const
repr.
Definition: py.hpp:531
bool is_int() const
is_int.
Definition: py.hpp:243
~obj() noexcept
dtor.
Definition: py.hpp:188
iter begin() const
get the begin iter.
Definition: py.hpp:787
exception: index_err.
Definition: _err.hpp:27
list to_list() const
get a list clone.
Definition: py.hpp:792
PyObject * transfer() noexcept
transfer the ownership of inner object.
Definition: py.hpp:206
bool operator<(const obj &o) const
&lt;
Definition: py.hpp:436
obj to_unicode() const
unicode.
Definition: py.hpp:554
set object
Definition: _set.hpp:5
obj type() const
py object type.
Definition: py.hpp:312
PPyObject p() const
get inner PyObject.
Definition: py.hpp:740
exception: val_err.
Definition: _err.hpp:43
iter end() const
get the end iter.
Definition: py.hpp:782
obj attr(const char *s) const
get attr.
Definition: py.hpp:370
const char * c_str() const
c_str().
Definition: py.hpp:292
obj call(const obj &args) const
call with args.
Definition: py.hpp:602
py tuple.
Definition: _tuple.hpp:5
iter for the c++11 range loop.
Definition: _iter.hpp:5
const obj operator[](const obj &o) const
get item.
Definition: py.hpp:677
obj a(const char *s) const
get attr, short form.
Definition: py.hpp:382
void release() noexcept
release the contained object
Definition: py.hpp:195
obj dir() const
py object dir.
Definition: py.hpp:720
long size() const
&#39;len&#39; as &#39;size&#39;.
Definition: py.hpp:626
bool has_attr(const obj &o) const
has attr.
Definition: py.hpp:343
void del_attr(const obj &a)
del attr.
Definition: py.hpp:414
bool has_attr(const char *s) const
has attr.
Definition: py.hpp:350
tuple to_tuple() const
get a tuple clone.
Definition: py.hpp:800
obj(const char *s)
str.
Definition: py.hpp:286
obj operator()(argT &&...a) const
call using operator.
Definition: py.hpp:591
obj attr(const obj &o) const
get attr.
Definition: py.hpp:358
long as_long() const
get long from obj
Definition: py.hpp:251
obj(std::initializer_list< obj > l)
tuple.
Definition: py.hpp:166
obj to_str() const
str.
Definition: py.hpp:542
bool has(const obj &x) const
&#39;in&#39; as &#39;has&#39;.
Definition: py.hpp:651
py list.
Definition: _list.hpp:5
void set_attr(const obj &a, const obj &v)
set attr.
Definition: py.hpp:394
obj(double v)
double ctor.
Definition: py.hpp:262
exception: type_err.
Definition: _err.hpp:35
bool is_callable() const
test callable.
Definition: py.hpp:583
bool is_float() const
is_float.
Definition: py.hpp:267
obj(long i)
long.
Definition: py.hpp:238