Browse Source

[1179] make iterator a real iterator

Jelte Jansen 13 years ago
parent
commit
bfa93c0ee7

+ 26 - 2
src/lib/python/isc/datasrc/iterator_python.cc

@@ -83,6 +83,11 @@ ZoneIterator_destroy(s_ZoneIterator* const self) {
 PyObject*
 ZoneIterator_getNextRRset(PyObject* po_self, PyObject*) {
     s_ZoneIterator* self = static_cast<s_ZoneIterator*>(po_self);
+    if (!self->cppobj) {
+        PyErr_SetString(getDataSourceException("Error"),
+                        "get_next_rrset() called past end of iterator");
+        return (NULL);
+    }
     try {
         isc::dns::ConstRRsetPtr rrset = self->cppobj->getNextRRset();
         if (!rrset) {
@@ -105,6 +110,23 @@ ZoneIterator_getNextRRset(PyObject* po_self, PyObject*) {
     }
 }
 
+PyObject*
+ZoneIterator_iter(PyObject *self) {
+    return (self);
+}
+
+PyObject*
+ZoneIterator_next(PyObject* self) {
+    PyObject *result = ZoneIterator_getNextRRset(self, NULL);
+    // iter_next must return NULL without error instead of Py_None
+    if (result == Py_None) {
+        Py_DECREF(result);
+        return (NULL);
+    } else {
+        return (result);
+    }
+}
+
 PyMethodDef ZoneIterator_methods[] = {
     { "get_next_rrset",
       reinterpret_cast<PyCFunction>(ZoneIterator_getNextRRset), METH_NOARGS,
@@ -144,8 +166,10 @@ PyTypeObject zoneiterator_type = {
     NULL,                               // tp_clear
     NULL,                               // tp_richcompare
     0,                                  // tp_weaklistoffset
-    NULL,                               // tp_iter
-    NULL,                               // tp_iternext
+    //reinterpret_cast<PyCFunction>(ZoneIterator_iter),                               // tp_iter
+    //reinterpret_cast<PyCFunction>(ZoneIterator_next),                               // tp_iternext
+    ZoneIterator_iter,
+    ZoneIterator_next,
     ZoneIterator_methods,               // tp_methods
     NULL,                               // tp_members
     NULL,                               // tp_getset

+ 2 - 6
src/lib/python/isc/datasrc/tests/datasrc_test.py

@@ -141,13 +141,9 @@ class DataSrcClient(unittest.TestCase):
                          "m. FAKEFAKEFAKEFAKE\n",
                          rrs.get_next_rrset().to_text())
         # there are more than 80 RRs in this zone... let's just count the rest
-        # hmm. this makes me think we might want a real iterator returned from
-        # get_iterator()
-        rrset = rrs.get_next_rrset()
         count = 0
-        while rrset is not None:
+        for rrset in rrs:
             count = count + 1
-            rrset = rrs.get_next_rrset()
         self.assertEqual(40, count)
         # TODO should we catch this (iterating past end) and just return None
         # instead of failing?
@@ -282,7 +278,7 @@ class DataSrcUpdater(unittest.TestCase):
 
         updater.commit()
         # second commit should raise exception
-        updater.commit()
+        self.assertRaises(isc.datasrc.Error, updater.commit)
 
         # the record should be gone now in the 'real' finder as well
         result, rrset = finder.find(isc.dns.Name("www.example.com"),