pythonhelpers.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) 2013-2017, Nucleic Development Team.
  3. |
  4. | Distributed under the terms of the Modified BSD License.
  5. |
  6. | The full license is in the file COPYING.txt, distributed with this software.
  7. |----------------------------------------------------------------------------*/
  8. #pragma once
  9. #include <Python.h>
  10. #include <structmember.h>
  11. #include <string>
  12. #if PY_MAJOR_VERSION >= 3
  13. #define FROM_STRING PyUnicode_FromString
  14. #define INITERROR return NULL
  15. #define MOD_INIT_FUNC(name) PyMODINIT_FUNC PyInit_##name(void)
  16. #else
  17. #define FROM_STRING PyString_FromString
  18. #define INITERROR return
  19. #define MOD_INIT_FUNC(name) PyMODINIT_FUNC init##name(void)
  20. #endif
  21. #ifndef Py_RETURN_NOTIMPLEMENTED
  22. #define Py_RETURN_NOTIMPLEMENTED \
  23. return Py_INCREF(Py_NotImplemented), Py_NotImplemented
  24. #endif
  25. #define pyobject_cast( o ) ( reinterpret_cast<PyObject*>( o ) )
  26. #define pytype_cast( o ) ( reinterpret_cast<PyTypeObject*>( o ) )
  27. struct module_state {
  28. PyObject *error;
  29. };
  30. namespace PythonHelpers
  31. {
  32. /*-----------------------------------------------------------------------------
  33. | Exception Handling
  34. |----------------------------------------------------------------------------*/
  35. inline PyObject*
  36. py_bad_internal_call( const char* message )
  37. {
  38. PyErr_SetString( PyExc_SystemError, message );
  39. return 0;
  40. }
  41. inline PyObject*
  42. py_type_fail( const char* message )
  43. {
  44. PyErr_SetString( PyExc_TypeError, message );
  45. return 0;
  46. }
  47. inline PyObject*
  48. py_expected_type_fail( PyObject* pyobj, const char* expected_type )
  49. {
  50. PyErr_Format(
  51. PyExc_TypeError,
  52. "Expected object of type `%s`. Got object of type `%s` instead.",
  53. expected_type, pyobj->ob_type->tp_name
  54. );
  55. return 0;
  56. }
  57. inline PyObject*
  58. py_value_fail( const char* message )
  59. {
  60. PyErr_SetString( PyExc_ValueError, message );
  61. return 0;
  62. }
  63. inline PyObject*
  64. py_runtime_fail( const char* message )
  65. {
  66. PyErr_SetString( PyExc_RuntimeError, message );
  67. return 0;
  68. }
  69. inline PyObject*
  70. py_attr_fail( const char* message )
  71. {
  72. PyErr_SetString( PyExc_AttributeError, message );
  73. return 0;
  74. }
  75. inline PyObject*
  76. py_no_attr_fail( PyObject* pyobj, const char* attr )
  77. {
  78. PyErr_Format(
  79. PyExc_AttributeError,
  80. "'%s' object has no attribute '%s'",
  81. pyobj->ob_type->tp_name, attr
  82. );
  83. return 0;
  84. }
  85. /*-----------------------------------------------------------------------------
  86. | Utilities
  87. |----------------------------------------------------------------------------*/
  88. inline PyObject*
  89. newref( PyObject* pyobj )
  90. {
  91. Py_INCREF( pyobj );
  92. return pyobj;
  93. }
  94. inline PyObject*
  95. xnewref( PyObject* pyobj )
  96. {
  97. Py_XINCREF( pyobj );
  98. return pyobj;
  99. }
  100. inline PyObject*
  101. py_bool( bool val )
  102. {
  103. return newref( val ? Py_True : Py_False );
  104. }
  105. inline PyCFunction
  106. lookup_method( PyTypeObject* type, const char* name )
  107. {
  108. PyMethodDef* method = type->tp_methods;
  109. for( ; method->ml_name != 0; ++method )
  110. {
  111. if( strcmp( method->ml_name, name ) == 0 )
  112. return method->ml_meth;
  113. }
  114. return 0;
  115. }
  116. /*-----------------------------------------------------------------------------
  117. | Object Ptr
  118. |----------------------------------------------------------------------------*/
  119. class PyObjectPtr {
  120. public:
  121. PyObjectPtr() : m_pyobj( 0 ) {}
  122. PyObjectPtr( const PyObjectPtr& objptr ) :
  123. m_pyobj( PythonHelpers::xnewref( objptr.m_pyobj ) ) {}
  124. PyObjectPtr( PyObject* pyobj ) : m_pyobj( pyobj ) {}
  125. ~PyObjectPtr()
  126. {
  127. xdecref_release();
  128. }
  129. PyObject* get() const
  130. {
  131. return m_pyobj;
  132. }
  133. void set( PyObject* pyobj )
  134. {
  135. PyObject* old = m_pyobj;
  136. m_pyobj = pyobj;
  137. Py_XDECREF( old );
  138. }
  139. PyObject* release()
  140. {
  141. PyObject* pyobj = m_pyobj;
  142. m_pyobj = 0;
  143. return pyobj;
  144. }
  145. PyObject* decref_release()
  146. {
  147. PyObject* pyobj = m_pyobj;
  148. m_pyobj = 0;
  149. Py_DECREF( pyobj );
  150. return pyobj;
  151. }
  152. PyObject* xdecref_release()
  153. {
  154. PyObject* pyobj = m_pyobj;
  155. m_pyobj = 0;
  156. Py_XDECREF( pyobj );
  157. return pyobj;
  158. }
  159. PyObject* incref_release()
  160. {
  161. PyObject* pyobj = m_pyobj;
  162. m_pyobj = 0;
  163. Py_INCREF( pyobj );
  164. return pyobj;
  165. }
  166. PyObject* xincref_release()
  167. {
  168. PyObject* pyobj = m_pyobj;
  169. m_pyobj = 0;
  170. Py_XINCREF( pyobj );
  171. return pyobj;
  172. }
  173. void incref() const
  174. {
  175. Py_INCREF( m_pyobj );
  176. }
  177. void decref() const
  178. {
  179. Py_DECREF( m_pyobj );
  180. }
  181. void xincref() const
  182. {
  183. Py_XINCREF( m_pyobj );
  184. }
  185. void xdecref() const
  186. {
  187. Py_XDECREF( m_pyobj );
  188. }
  189. PyObject* newref() const
  190. {
  191. Py_INCREF( m_pyobj );
  192. return m_pyobj;
  193. }
  194. PyObject* xnewref() const
  195. {
  196. Py_XINCREF( m_pyobj );
  197. return m_pyobj;
  198. }
  199. size_t refcount() const
  200. {
  201. if( m_pyobj )
  202. return m_pyobj->ob_refcnt;
  203. return 0;
  204. }
  205. bool is_true( bool clear_err=true ) const
  206. {
  207. int truth = PyObject_IsTrue( m_pyobj );
  208. if( truth == 1 )
  209. return true;
  210. if( truth == 0 )
  211. return false;
  212. if( clear_err )
  213. PyErr_Clear();
  214. return false;
  215. }
  216. bool is_None() const
  217. {
  218. return m_pyobj == Py_None;
  219. }
  220. bool is_True() const
  221. {
  222. return m_pyobj == Py_True;
  223. }
  224. bool is_False() const
  225. {
  226. return m_pyobj == Py_False;
  227. }
  228. bool load_dict( PyObjectPtr& out, bool forcecreate=false )
  229. {
  230. PyObject** dict = _PyObject_GetDictPtr( m_pyobj );
  231. if( !dict )
  232. return false;
  233. if( forcecreate && !*dict )
  234. *dict = PyDict_New();
  235. out = PythonHelpers::xnewref( *dict );
  236. return true;
  237. }
  238. bool richcompare( PyObject* other, int opid, bool clear_err=true )
  239. {
  240. int r = PyObject_RichCompareBool( m_pyobj, other, opid );
  241. if( r == 1 )
  242. return true;
  243. if( r == 0 )
  244. return false;
  245. if( clear_err && PyErr_Occurred() )
  246. PyErr_Clear();
  247. return false;
  248. }
  249. bool richcompare( PyObjectPtr& other, int opid, bool clear_err=true )
  250. {
  251. return richcompare( other.m_pyobj, opid, clear_err );
  252. }
  253. bool hasattr( PyObject* attr )
  254. {
  255. return PyObject_HasAttr( m_pyobj, attr ) == 1;
  256. }
  257. bool hasattr( PyObjectPtr& attr )
  258. {
  259. return PyObject_HasAttr( m_pyobj, attr.get() ) == 1;
  260. }
  261. bool hasattr( const char* attr )
  262. {
  263. return PyObject_HasAttrString( m_pyobj, attr ) == 1;
  264. }
  265. bool hasattr( std::string& attr )
  266. {
  267. return hasattr( attr.c_str() );
  268. }
  269. PyObjectPtr getattr( PyObject* attr )
  270. {
  271. return PyObjectPtr( PyObject_GetAttr( m_pyobj, attr ) );
  272. }
  273. PyObjectPtr getattr( PyObjectPtr& attr )
  274. {
  275. return PyObjectPtr( PyObject_GetAttr( m_pyobj, attr.get() ) );
  276. }
  277. PyObjectPtr getattr( const char* attr )
  278. {
  279. return PyObjectPtr( PyObject_GetAttrString( m_pyobj, attr ) );
  280. }
  281. PyObjectPtr getattr( std::string& attr )
  282. {
  283. return getattr( attr.c_str() );
  284. }
  285. bool setattr( PyObject* attr, PyObject* value )
  286. {
  287. return PyObject_SetAttr( m_pyobj, attr, value ) == 0;
  288. }
  289. bool setattr( PyObjectPtr& attr, PyObjectPtr& value )
  290. {
  291. return PyObject_SetAttr( m_pyobj, attr.get(), value.get() ) == 0;
  292. }
  293. PyObjectPtr operator()( PyObjectPtr& args ) const
  294. {
  295. return PyObjectPtr( PyObject_Call( m_pyobj, args.get(), 0 ) );
  296. }
  297. PyObjectPtr operator()( PyObjectPtr& args, PyObjectPtr& kwargs ) const
  298. {
  299. return PyObjectPtr( PyObject_Call( m_pyobj, args.get(), kwargs.get() ) );
  300. }
  301. operator void*() const
  302. {
  303. return static_cast<void*>( m_pyobj );
  304. }
  305. PyObjectPtr& operator=( const PyObjectPtr& rhs )
  306. {
  307. PyObject* old = m_pyobj;
  308. m_pyobj = rhs.m_pyobj;
  309. Py_XINCREF( m_pyobj );
  310. Py_XDECREF( old );
  311. return *this;
  312. }
  313. PyObjectPtr& operator=( PyObject* rhs )
  314. {
  315. PyObject* old = m_pyobj;
  316. m_pyobj = rhs;
  317. Py_XDECREF( old );
  318. return *this;
  319. }
  320. protected:
  321. PyObject* m_pyobj;
  322. };
  323. inline bool
  324. operator!=( const PyObjectPtr& lhs, const PyObjectPtr& rhs )
  325. {
  326. return lhs.get() != rhs.get();
  327. }
  328. inline bool
  329. operator!=( const PyObject* lhs, const PyObjectPtr& rhs )
  330. {
  331. return lhs != rhs.get();
  332. }
  333. inline bool
  334. operator!=( const PyObjectPtr& lhs, const PyObject* rhs )
  335. {
  336. return lhs.get() != rhs;
  337. }
  338. inline bool
  339. operator==( const PyObjectPtr& lhs, const PyObjectPtr& rhs )
  340. {
  341. return lhs.get() == rhs.get();
  342. }
  343. inline bool
  344. operator==( const PyObject* lhs, const PyObjectPtr& rhs )
  345. {
  346. return lhs == rhs.get();
  347. }
  348. inline bool
  349. operator==( const PyObjectPtr& lhs, const PyObject* rhs )
  350. {
  351. return lhs.get() == rhs;
  352. }
  353. /*-----------------------------------------------------------------------------
  354. | Tuple Ptr
  355. |----------------------------------------------------------------------------*/
  356. class PyTuplePtr : public PyObjectPtr {
  357. public:
  358. PyTuplePtr() : PyObjectPtr() {}
  359. PyTuplePtr( const PyObjectPtr& objptr ) : PyObjectPtr( objptr ) {}
  360. PyTuplePtr( PyObject* pytuple ) : PyObjectPtr( pytuple ) {}
  361. bool check()
  362. {
  363. return PyTuple_Check( m_pyobj );
  364. }
  365. bool check_exact()
  366. {
  367. return PyTuple_CheckExact( m_pyobj );
  368. }
  369. Py_ssize_t size() const
  370. {
  371. return PyTuple_GET_SIZE( m_pyobj );
  372. }
  373. PyObjectPtr get_item( Py_ssize_t index ) const
  374. {
  375. return PyObjectPtr( PythonHelpers::newref( PyTuple_GET_ITEM( m_pyobj, index ) ) );
  376. }
  377. void set_item( Py_ssize_t index, PyObject* pyobj )
  378. {
  379. PyObject* old_item = PyTuple_GET_ITEM( m_pyobj, index );
  380. PyTuple_SET_ITEM( m_pyobj, index, pyobj );
  381. Py_XDECREF( old_item );
  382. }
  383. void set_item( Py_ssize_t index, PyObjectPtr& item )
  384. {
  385. PyObject* old_item = PyTuple_GET_ITEM( m_pyobj, index );
  386. PyTuple_SET_ITEM( m_pyobj, index, item.get() );
  387. Py_XINCREF( item.get() );
  388. Py_XDECREF( old_item );
  389. }
  390. // pyobj must not be null, only use to fill a new empty tuple
  391. void initialize( Py_ssize_t index, PyObject* pyobj )
  392. {
  393. PyTuple_SET_ITEM( m_pyobj, index, pyobj );
  394. }
  395. // ptr must not be empty, only use to fill a new empty tuple
  396. void initialize( Py_ssize_t index, PyObjectPtr& item )
  397. {
  398. PyTuple_SET_ITEM( m_pyobj, index, item.get() );
  399. Py_INCREF( item.get() );
  400. }
  401. };
  402. /*-----------------------------------------------------------------------------
  403. | List Ptr
  404. |----------------------------------------------------------------------------*/
  405. class PyListPtr : public PyObjectPtr {
  406. public:
  407. PyListPtr() : PyObjectPtr() {}
  408. PyListPtr( const PyObjectPtr& objptr ) : PyObjectPtr( objptr ) {}
  409. PyListPtr( PyObject* pylist ) : PyObjectPtr( pylist ) {}
  410. bool check() const
  411. {
  412. return PyList_Check( m_pyobj );
  413. }
  414. bool check_exact() const
  415. {
  416. return PyList_CheckExact( m_pyobj );
  417. }
  418. Py_ssize_t size() const
  419. {
  420. return PyList_GET_SIZE( m_pyobj );
  421. }
  422. PyObject* borrow_item( Py_ssize_t index ) const
  423. {
  424. return PyList_GET_ITEM( m_pyobj, index );
  425. }
  426. PyObjectPtr get_item( Py_ssize_t index ) const
  427. {
  428. return PyObjectPtr( PythonHelpers::newref( PyList_GET_ITEM( m_pyobj, index ) ) );
  429. }
  430. void set_item( Py_ssize_t index, PyObject* pyobj ) const
  431. {
  432. PyObject* old_item = PyList_GET_ITEM( m_pyobj, index );
  433. PyList_SET_ITEM( m_pyobj, index, pyobj );
  434. Py_XDECREF( old_item );
  435. }
  436. void set_item( Py_ssize_t index, PyObjectPtr& item ) const
  437. {
  438. PyObject* old_item = PyList_GET_ITEM( m_pyobj, index );
  439. PyList_SET_ITEM( m_pyobj, index, item.get() );
  440. Py_XINCREF( item.get() );
  441. Py_XDECREF( old_item );
  442. }
  443. bool del_item( Py_ssize_t index ) const
  444. {
  445. if( PySequence_DelItem( m_pyobj, index ) == -1 )
  446. return false;
  447. return true;
  448. }
  449. bool append( PyObjectPtr& pyobj ) const
  450. {
  451. if( PyList_Append( m_pyobj, pyobj.get() ) == 0 )
  452. return true;
  453. return false;
  454. }
  455. Py_ssize_t index( PyObjectPtr& item ) const
  456. {
  457. Py_ssize_t maxidx = size();
  458. for( Py_ssize_t idx = 0; idx < maxidx; idx++ )
  459. {
  460. PyObjectPtr other( get_item( idx ) );
  461. if( item.richcompare( other, Py_EQ ) )
  462. return idx;
  463. }
  464. return -1;
  465. }
  466. };
  467. /*-----------------------------------------------------------------------------
  468. | Dict Ptr
  469. |----------------------------------------------------------------------------*/
  470. class PyDictPtr : public PyObjectPtr {
  471. public:
  472. PyDictPtr() : PyObjectPtr() {}
  473. PyDictPtr( const PyObjectPtr& objptr ) : PyObjectPtr( objptr ) {}
  474. PyDictPtr( PyObject* pydict ) : PyObjectPtr( pydict ) {}
  475. bool check()
  476. {
  477. return PyDict_Check( m_pyobj );
  478. }
  479. bool check_exact()
  480. {
  481. return PyDict_CheckExact( m_pyobj );
  482. }
  483. Py_ssize_t size() const
  484. {
  485. return PyDict_Size( m_pyobj );
  486. }
  487. PyObjectPtr get_item( PyObject* key ) const
  488. {
  489. return PyObjectPtr( PythonHelpers::xnewref( PyDict_GetItem( m_pyobj, key ) ) ) ;
  490. }
  491. PyObjectPtr get_item( PyObjectPtr& key ) const
  492. {
  493. return PyObjectPtr( PythonHelpers::xnewref( PyDict_GetItem( m_pyobj, key.get() ) ) );
  494. }
  495. PyObjectPtr get_item( const char* key ) const
  496. {
  497. return PyObjectPtr( PythonHelpers::xnewref( PyDict_GetItemString( m_pyobj, key ) ) );
  498. }
  499. PyObjectPtr get_item( std::string& key ) const
  500. {
  501. return get_item( key.c_str() );
  502. }
  503. bool set_item( PyObject* key, PyObject* value ) const
  504. {
  505. if( PyDict_SetItem( m_pyobj, key, value ) == 0 )
  506. return true;
  507. return false;
  508. }
  509. bool set_item( PyObject* key, PyObjectPtr& value ) const
  510. {
  511. if( PyDict_SetItem( m_pyobj, key, value.get() ) == 0 )
  512. return true;
  513. return false;
  514. }
  515. bool set_item( PyObjectPtr& key, PyObject* value ) const
  516. {
  517. if( PyDict_SetItem( m_pyobj, key.get(), value ) == 0 )
  518. return true;
  519. return false;
  520. }
  521. bool set_item( PyObjectPtr& key, PyObjectPtr& value ) const
  522. {
  523. if( PyDict_SetItem( m_pyobj, key.get(), value.get() ) == 0 )
  524. return true;
  525. return false;
  526. }
  527. bool set_item( const char* key, PyObjectPtr& value ) const
  528. {
  529. if( PyDict_SetItemString( m_pyobj, key, value.get() ) == 0 )
  530. return true;
  531. return false;
  532. }
  533. bool set_item( const char* key, PyObject* value ) const
  534. {
  535. if( PyDict_SetItemString( m_pyobj, key, value ) == 0 )
  536. return true;
  537. return false;
  538. }
  539. bool set_item( std::string& key, PyObjectPtr& value ) const
  540. {
  541. return set_item( key.c_str(), value );
  542. }
  543. bool del_item( PyObjectPtr& key ) const
  544. {
  545. if( PyDict_DelItem( m_pyobj, key.get() ) == 0 )
  546. return true;
  547. return false;
  548. }
  549. bool del_item( const char* key ) const
  550. {
  551. if( PyDict_DelItemString( m_pyobj, key ) == 0 )
  552. return true;
  553. return false;
  554. }
  555. bool del_item( std::string& key ) const
  556. {
  557. return del_item( key.c_str() );
  558. }
  559. };
  560. /*-----------------------------------------------------------------------------
  561. | Method Ptr
  562. |----------------------------------------------------------------------------*/
  563. class PyMethodPtr : public PyObjectPtr {
  564. public:
  565. PyMethodPtr() : PyObjectPtr() {}
  566. PyMethodPtr( const PyObjectPtr& objptr ) : PyObjectPtr( objptr ) {}
  567. PyMethodPtr( PyObject* pymethod ) : PyObjectPtr( pymethod ) {}
  568. bool check()
  569. {
  570. return PyMethod_Check( m_pyobj );
  571. }
  572. PyObjectPtr get_self() const
  573. {
  574. return PyObjectPtr( PythonHelpers::xnewref( PyMethod_GET_SELF( m_pyobj ) ) );
  575. }
  576. PyObjectPtr get_function() const
  577. {
  578. return PyObjectPtr( PythonHelpers::xnewref( PyMethod_GET_FUNCTION( m_pyobj ) ) );
  579. }
  580. #if PY_MAJOR_VERSION < 3
  581. PyObjectPtr get_class() const
  582. {
  583. return PyObjectPtr( PythonHelpers::xnewref( PyMethod_GET_CLASS( m_pyobj ) ) );
  584. }
  585. #endif
  586. };
  587. /*-----------------------------------------------------------------------------
  588. | Weakref Ptr
  589. |----------------------------------------------------------------------------*/
  590. class PyWeakrefPtr : public PyObjectPtr {
  591. public:
  592. PyWeakrefPtr() : PyObjectPtr() {}
  593. PyWeakrefPtr( const PyObjectPtr& objptr ) : PyObjectPtr( objptr ) {}
  594. PyWeakrefPtr( PyObject* pyweakref ) : PyObjectPtr( pyweakref ) {}
  595. bool check()
  596. {
  597. return PyWeakref_CheckRef( m_pyobj );
  598. }
  599. bool check_exact()
  600. {
  601. return PyWeakref_CheckRefExact( m_pyobj );
  602. }
  603. PyObjectPtr get_object() const
  604. {
  605. return PyObjectPtr( PythonHelpers::newref( PyWeakref_GET_OBJECT( m_pyobj ) ) );
  606. }
  607. };
  608. } // namespace PythonHelpers