iterator_python.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // Enable this if you use s# variants with PyArg_ParseTuple(), see
  15. // http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
  16. //#define PY_SSIZE_T_CLEAN
  17. // Python.h needs to be placed at the head of the program file, see:
  18. // http://docs.python.org/py3k/extending/extending.html#a-simple-example
  19. #include <Python.h>
  20. #include <string>
  21. #include <stdexcept>
  22. #include <util/python/pycppwrapper_util.h>
  23. #include <datasrc/client.h>
  24. #include <datasrc/database.h>
  25. #include <datasrc/sqlite3_accessor.h>
  26. #include <datasrc/iterator.h>
  27. #include <dns/python/name_python.h>
  28. #include <dns/python/rrset_python.h>
  29. #include "datasrc.h"
  30. #include "iterator_python.h"
  31. #include "iterator_inc.cc"
  32. using namespace std;
  33. using namespace isc::util::python;
  34. using namespace isc::datasrc;
  35. using namespace isc::datasrc::python;
  36. //
  37. // Definition of the classes
  38. //
  39. // For each class, we need a struct, a helper functions (init, destroy,
  40. // and static wrappers around the methods we export), a list of methods,
  41. // and a type description
  42. //
  43. // Zone Iterator
  44. //
  45. // Trivial constructor.
  46. s_ZoneIterator::s_ZoneIterator() : cppobj(ZoneIteratorPtr()) {
  47. }
  48. namespace {
  49. // Shortcut type which would be convenient for adding class variables safely.
  50. typedef CPPPyObjectContainer<s_ZoneIterator, ZoneIterator> ZoneIteratorContainer;
  51. // General creation and destruction
  52. int
  53. ZoneIterator_init(s_ZoneIterator* self, PyObject* args) {
  54. // can't be called directly
  55. PyErr_SetString(PyExc_TypeError,
  56. "ZoneIterator cannot be constructed directly");
  57. return (-1);
  58. }
  59. // This is a template of typical code logic of python object destructor.
  60. // In many cases you can use it without modification, but check that carefully.
  61. void
  62. ZoneIterator_destroy(s_ZoneIterator* const self) {
  63. // cppobj is a shared ptr so no need to delete that
  64. Py_TYPE(self)->tp_free(self);
  65. }
  66. //
  67. // We declare the functions here, the definitions are below
  68. // the type definition of the object, since both can use the other
  69. //
  70. PyObject* ZoneIterator_getNextRRset(PyObject* po_self, PyObject*) {
  71. s_ZoneIterator* self = static_cast<s_ZoneIterator*>(po_self);
  72. try {
  73. isc::dns::ConstRRsetPtr rrset = self->cppobj->getNextRRset();
  74. if (!rrset) {
  75. Py_RETURN_NONE;
  76. }
  77. return (isc::dns::python::createRRsetObject(*rrset));
  78. } catch (const isc::Exception& isce) {
  79. // isc::Unexpected is thrown when we call getNextRRset() when we are
  80. // already done iterating ('iterating past end')
  81. // We could also simply return None again
  82. PyErr_SetString(getDataSourceException("Error"), isce.what());
  83. return (NULL);
  84. } catch (const std::exception& exc) {
  85. PyErr_SetString(getDataSourceException("Error"), exc.what());
  86. return (NULL);
  87. }
  88. }
  89. // These are the functions we export
  90. //
  91. // These are the functions we export
  92. // For a minimal support, we don't need them.
  93. // This list contains the actual set of functions we have in
  94. // python. Each entry has
  95. // 1. Python method name
  96. // 2. Our static function here
  97. // 3. Argument type
  98. // 4. Documentation
  99. PyMethodDef ZoneIterator_methods[] = {
  100. { "get_next_rrset", reinterpret_cast<PyCFunction>(ZoneIterator_getNextRRset),
  101. METH_NOARGS, ZoneIterator_getNextRRset_doc },
  102. { NULL, NULL, 0, NULL }
  103. };
  104. } // end of unnamed namespace
  105. namespace isc {
  106. namespace datasrc {
  107. namespace python {
  108. PyTypeObject zoneiterator_type = {
  109. PyVarObject_HEAD_INIT(NULL, 0)
  110. "datasrc.ZoneIterator",
  111. sizeof(s_ZoneIterator), // tp_basicsize
  112. 0, // tp_itemsize
  113. reinterpret_cast<destructor>(ZoneIterator_destroy), // tp_dealloc
  114. NULL, // tp_print
  115. NULL, // tp_getattr
  116. NULL, // tp_setattr
  117. NULL, // tp_reserved
  118. NULL, // tp_repr
  119. NULL, // tp_as_number
  120. NULL, // tp_as_sequence
  121. NULL, // tp_as_mapping
  122. NULL, // tp_hash
  123. NULL, // tp_call
  124. NULL, // tp_str
  125. NULL, // tp_getattro
  126. NULL, // tp_setattro
  127. NULL, // tp_as_buffer
  128. Py_TPFLAGS_DEFAULT, // tp_flags
  129. ZoneIterator_doc,
  130. NULL, // tp_traverse
  131. NULL, // tp_clear
  132. NULL, // tp_richcompare
  133. 0, // tp_weaklistoffset
  134. NULL, // tp_iter
  135. NULL, // tp_iternext
  136. ZoneIterator_methods, // tp_methods
  137. NULL, // tp_members
  138. NULL, // tp_getset
  139. NULL, // tp_base
  140. NULL, // tp_dict
  141. NULL, // tp_descr_get
  142. NULL, // tp_descr_set
  143. 0, // tp_dictoffset
  144. reinterpret_cast<initproc>(ZoneIterator_init),// tp_init
  145. NULL, // tp_alloc
  146. PyType_GenericNew, // tp_new
  147. NULL, // tp_free
  148. NULL, // tp_is_gc
  149. NULL, // tp_bases
  150. NULL, // tp_mro
  151. NULL, // tp_cache
  152. NULL, // tp_subclasses
  153. NULL, // tp_weaklist
  154. NULL, // tp_del
  155. 0 // tp_version_tag
  156. };
  157. // Module Initialization, all statics are initialized here
  158. bool
  159. initModulePart_ZoneIterator(PyObject* mod) {
  160. // We initialize the static description object with PyType_Ready(),
  161. // then add it to the module. This is not just a check! (leaving
  162. // this out results in segmentation faults)
  163. if (PyType_Ready(&zoneiterator_type) < 0) {
  164. return (false);
  165. }
  166. void* zip = &zoneiterator_type;
  167. if (PyModule_AddObject(mod, "ZoneIterator", static_cast<PyObject*>(zip)) < 0) {
  168. return (false);
  169. }
  170. Py_INCREF(&zoneiterator_type);
  171. return (true);
  172. }
  173. PyObject*
  174. createZoneIteratorObject(isc::datasrc::ZoneIteratorPtr source) {
  175. s_ZoneIterator* py_zi = static_cast<s_ZoneIterator*>(
  176. zoneiterator_type.tp_alloc(&zoneiterator_type, 0));
  177. if (py_zi != NULL) {
  178. py_zi->cppobj = source;
  179. }
  180. return (py_zi);
  181. }
  182. } // namespace python
  183. } // namespace datasrc
  184. } // namespace isc