[svn] commit: r3321 - in /branches/trac375/src/lib/datasrc/python: pydatasrc.cc tests/pydatasrc_test.py

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Oct 22 14:14:34 UTC 2010


Author: jelte
Date: Fri Oct 22 14:14:33 2010
New Revision: 3321

Log:
callback functionality for do_ixfr wrapper function as well (+tests of course)


Modified:
    branches/trac375/src/lib/datasrc/python/pydatasrc.cc
    branches/trac375/src/lib/datasrc/python/tests/pydatasrc_test.py

Modified: branches/trac375/src/lib/datasrc/python/pydatasrc.cc
==============================================================================
--- branches/trac375/src/lib/datasrc/python/pydatasrc.cc (original)
+++ branches/trac375/src/lib/datasrc/python/pydatasrc.cc Fri Oct 22 14:14:33 2010
@@ -257,7 +257,13 @@
       "Perform an IXFR with the given List of RRsets as IXFR input.\n"
       "This method takes the following arguments:\n"
       "DataSrcTransaction transaction: The current transaction\n"
-      "List answer_section: The answer section from the query response\n"
+      "List or Iterator: The second argument can be either a List\n"
+      "                  containing RRset objects, or an iterator\n"
+      "                  function that yields RRset objects.\n"
+      "arg1: optional argument that is passed on to the iterator\n"
+      "      function\n"
+      "arg2: optional argument that is passed on to the iterator\n"
+      "      function\n"
       "\n"
       "Returns DataSrc.W_SUCCESS on success. An error value otherwise\n"
     },
@@ -1022,7 +1028,7 @@
                          &rrset_obj)) {
         isc::dns::ConstRRsetPtr rrset_ptr = PyRRset_AsRRsetPtr(rrset_obj);
         
-        PyObject* result = Py_BuildValue("I",
+        PyObject* result = Py_BuildValue(0,
                               self->datasrc->delRRset(
                               *(transaction->datasrc_transaction),
                               rrset_ptr));
@@ -1180,43 +1186,66 @@
 static PyObject*
 DataSrc_doIXFR(s_DataSrc* self, PyObject* args) {
     s_DataSrcTransaction *transaction;
-    PyObject *rrset_list_obj;
+    PyObject* rrset_list_or_function_obj;
+    PyObject* arg1 = NULL;
+    PyObject* arg2 = NULL;
     
-    if (PyArg_ParseTuple(args, "O!O",
+    if (PyArg_ParseTuple(args, "O!O|OO",
                          &datasrc_transaction_type, &transaction,
-                         &rrset_list_obj)) {
-        if (!PyList_Check(rrset_list_obj)) {
-            PyErr_SetString(PyExc_TypeError,
-                            "argument 2 of do_ixfr() is not a List");
-            return (NULL);
-        }
-        // ok we should probably change the API for doIXFR there
-        // for now create a fake message (we need the sectioniterator
-        // for the call right now)
-        isc::dns::Message m(isc::dns::Message::RENDER);
-        for (int i = 0; i < PyList_Size(rrset_list_obj); ++i) {
-            PyObject* rrset_obj = PyList_GET_ITEM(rrset_list_obj, i);
-            if (!PyRRset_Check(rrset_obj)) {
-                PyErr_SetString(PyExc_TypeError,
-                    "non-RRset object in argument 2 of do_ixfr()");
+                         &rrset_list_or_function_obj,
+                         &arg1, &arg2)) {
+        if (PyList_Check(rrset_list_or_function_obj)) {
+            std::vector<isc::dns::RRsetPtr> rrset_list;
+            for (int i = 0; i < PyList_Size(rrset_list_or_function_obj); ++i) {
+                PyObject* rrset_obj = PyList_GET_ITEM(rrset_list_or_function_obj, i);
+                if (!PyRRset_Check(rrset_obj)) {
+                    PyErr_SetString(PyExc_TypeError,
+                        "non-RRset object in the list at argument 2 of replace_zone()");
+                    return (NULL);
+                }
+                rrset_list.push_back(PyRRset_AsRRsetPtr(rrset_obj));
+            }
+            size_t i = 0;
+            PyObject* result = Py_BuildValue("I",
+                                  self->datasrc->doIXFR(
+                                  *(transaction->datasrc_transaction),
+                                  isc::datasrc::callbackHelperRRsetVector,
+                                  &rrset_list, &i));
+            return (result);
+        } else if (PyCallable_Check(rrset_list_or_function_obj)) {
+            PyObject* iterator = PyObject_CallFunctionObjArgs(rrset_list_or_function_obj, arg1, arg2, NULL);
+            if (!iterator) {
                 return (NULL);
             }
-            m.addRRset(isc::dns::Section::ANSWER(), PyRRset_AsRRsetPtr(rrset_obj), false);
-        }
-
-        isc::dns::RRsetIterator begin = m.beginSection(isc::dns::Section::ANSWER());
-        isc::dns::RRsetIterator end = m.endSection(isc::dns::Section::ANSWER());
-        PyObject* result = Py_BuildValue("I",
-                              self->datasrc->doIXFR(
-                              *(transaction->datasrc_transaction),
-                              isc::datasrc::callbackHelperRRsetIterator,
-                              &begin,
-                              &end));
-        return (result);
+            if (!PyIter_Check(iterator)) {
+                PyErr_SetString(PyExc_TypeError,
+                    "Callback in replace_zone() is not an iterator");
+                return (NULL);
+            }
+            try {
+                PyObject* result = Py_BuildValue("I",
+                                      self->datasrc->doIXFR(
+                                      *(transaction->datasrc_transaction),
+                                      callback_iterator,
+                                      iterator, NULL
+                                      ));
+                return (result);
+            } catch (NotRRsetException) {
+                PyErr_SetString(PyExc_TypeError,
+                    "non-RRset object returned by iterator in replace_zone()");
+                return (NULL);
+            } catch (CallbackException) {
+                // specific error already set, just return NULL
+                return (NULL);
+            }
+        } else {
+            PyErr_SetString(PyExc_TypeError,
+                            "argument 2 of replace_zone() is not a List or a function");
+            return (NULL);
+        }
     }
     return (NULL);
 }
-
 
 
 //

Modified: branches/trac375/src/lib/datasrc/python/tests/pydatasrc_test.py
==============================================================================
--- branches/trac375/src/lib/datasrc/python/tests/pydatasrc_test.py (original)
+++ branches/trac375/src/lib/datasrc/python/tests/pydatasrc_test.py Fri Oct 22 14:14:33 2010
@@ -498,7 +498,8 @@
         result = self.ds.start_transaction(transaction)
         self.assertEqual(DataSrc.W_SUCCESS, result)
 
-        new_rrs = [ "Something that is not an RRset" ]
+        # For this test content does not matter as long as it's not an RRset
+        new_rrs = [ 1 ]
 
         self.assertRaises(TypeError, self.ds.replace_zone, transaction, get_new_rrs_no_args, new_rrs)
         result = self.ds.rollback_transaction(transaction)
@@ -509,7 +510,8 @@
         result = self.ds.start_transaction(transaction)
         self.assertEqual(DataSrc.W_SUCCESS, result)
 
-        new_rrs = [ "Something that is not an RRset" ]
+        # For this test content does not matter as long as it's something
+        new_rrs = [ 1 ]
 
         self.assertRaises(TypeError, self.ds.replace_zone, transaction, get_new_rrs_bad, new_rrs)
         result = self.ds.rollback_transaction(transaction)
@@ -556,7 +558,7 @@
         self.assertRaises(TypeError, self.ds.update_check_prerequisite, 1)
         self.assertRaises(TypeError, self.ds.update_check_prerequisite, [])
     
-    def test_do_ixfr_ok(self):
+    def test_do_ixfr_list(self):
         rrsets = rrsets_from_file(testdata_path + "/ixfr_ok.rrs")
 
         result = []
@@ -580,6 +582,74 @@
         self.assertEqual(DataSrc.SUCCESS, n);
         self.assertEqual(1, len(result))
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.3\n", str(result[0]))
+
+    def test_do_ixfr_list_bad(self):
+        rrsets = [ 1 ]
+
+        transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+        result = self.ds.start_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        self.assertRaises(TypeError, self.ds.do_ixfr, transaction, rrsets)
+
+    def test_do_ixfr_function(self):
+        rrsets = rrsets_from_file(testdata_path + "/ixfr_ok.rrs")
+
+        result = []
+        n = self.ds.find_addrs(Name("www.example.com"), RRClass.IN(), result, 0, Name("example.com"))
+        self.assertEqual(DataSrc.SUCCESS, n);
+        self.assertEqual(1, len(result))
+        self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n", str(result[0]))
+
+        transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+        result = self.ds.start_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        result = self.ds.do_ixfr(transaction, get_new_rrs, rrsets)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        result = self.ds.commit_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+        
+        result = []
+        n = self.ds.find_addrs(Name("www.example.com"), RRClass.IN(), result, 0, Name("example.com"))
+        self.assertEqual(DataSrc.SUCCESS, n);
+        self.assertEqual(1, len(result))
+        self.assertEqual("www.example.com. 3600 IN A 192.0.2.3\n", str(result[0]))
+
+    def test_do_ixfr_function_bad_call(self):
+        transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+        result = self.ds.start_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        rrsets = rrsets_from_file(testdata_path + "/ixfr_ok.rrs")
+        self.assertRaises(TypeError, self.ds.do_ixfr, transaction, get_new_rrs_no_args, rrsets)
+
+    def test_do_ixfr_function_no_iter(self):
+        transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+        result = self.ds.start_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        rrsets = rrsets_from_file(testdata_path + "/ixfr_ok.rrs")
+        self.assertRaises(TypeError, self.ds.do_ixfr, transaction, get_new_rrs_no_iter, rrsets)
+
+    def test_do_ixfr_function_not_rrset(self):
+        transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+        result = self.ds.start_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        # For this test content does not matter as long as it's not an RRset
+        rrsets = [ 1 ]
+        self.assertRaises(TypeError, self.ds.do_ixfr, transaction, get_new_rrs, rrsets)
+
+    def test_do_ixfr_function_that_raises(self):
+        transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+        result = self.ds.start_transaction(transaction)
+        self.assertEqual(DataSrc.W_SUCCESS, result)
+
+        rrsets = rrsets_from_file(testdata_path + "/ixfr_ok.rrs")
+        self.assertRaises(TypeError, self.ds.do_ixfr, transaction, get_new_rrs_bad, rrsets)
+
         
     def test_do_ixfr_bad(self):
         rrsets = rrsets_from_file(testdata_path + "/ixfr_bad_remove_nonexisting.rrs")




More information about the bind10-changes mailing list