Browse Source

[2051] Implement the find wrapper

However, it still needs documentation and some stuff with object
lifetime management.
Michal 'vorner' Vaner 12 years ago
parent
commit
cf2ea3f88a

+ 11 - 0
src/lib/python/isc/datasrc/client_python.cc

@@ -348,6 +348,17 @@ PyTypeObject datasourceclient_type = {
     0                                   // tp_version_tag
 };
 
+PyObject*
+wrapDataSourceClient(DataSourceClient* client) {
+    // There aro no exceptions here, so this is safe
+    s_DataSourceClient *result =
+        static_cast<s_DataSourceClient*>(PyObject_New(s_DataSourceClient,
+                                                      &datasourceclient_type));
+    result->cppobj = NULL;
+    result->client = client;
+    return (result);
+}
+
 } // namespace python
 } // namespace datasrc
 } // namespace isc

+ 3 - 0
src/lib/python/isc/datasrc/client_python.h

@@ -25,6 +25,9 @@ namespace python {
 
 extern PyTypeObject datasourceclient_type;
 
+// TODO: Documentation, warning
+PyObject* wrapDataSourceClient(DataSourceClient* client);
+
 } // namespace python
 } // namespace datasrc
 } // namespace isc

+ 50 - 3
src/lib/python/isc/datasrc/configurableclientlist_python.cc

@@ -26,12 +26,15 @@
 #include <util/python/pycppwrapper_util.h>
 
 #include <dns/python/rrclass_python.h>
+#include <dns/python/name_python.h>
 
 #include <datasrc/client_list.h>
 
 #include "configurableclientlist_python.h"
 #include "datasrc.h"
 #include "configurableclientlist_inc.cc"
+#include "finder_python.h"
+#include "client_python.h"
 
 using namespace std;
 using namespace isc::util::python;
@@ -47,9 +50,6 @@ s_ConfigurableClientList::s_ConfigurableClientList() : cppobj(NULL) {
 }
 
 namespace {
-// Shortcut type which would be convenient for adding class variables safely.
-typedef CPPPyObjectContainer<s_ConfigurableClientList, ConfigurableClientList>
-    ConfigurableClientListContainer;
 
 int
 ConfigurableClientList_init(PyObject* po_self, PyObject* args, PyObject*) {
@@ -111,6 +111,52 @@ ConfigurableClientList_configure(PyObject* po_self, PyObject* args) {
     }
 }
 
+PyObject*
+ConfigurableClientList_find(PyObject* po_self, PyObject* args) {
+    s_ConfigurableClientList* self =
+        static_cast<s_ConfigurableClientList*>(po_self);
+    try {
+        PyObject* name_obj;
+        int want_exact_match = 0;
+        int want_finder = 1;
+        if (PyArg_ParseTuple(args, "O!|ii", &isc::dns::python::name_type,
+                             &name_obj, &want_exact_match, &want_finder)) {
+            const isc::dns::Name
+                name(isc::dns::python::PyName_ToName(name_obj));
+            const ClientList::FindResult
+                result(self->cppobj->find(name, want_exact_match,
+                                          want_finder));
+            PyObjectContainer dsrc;
+            if (result.dsrc_client_ == NULL) {
+                // Use the Py_BuildValue, as it takes care of the
+                // reference counts correctly.
+                dsrc.reset(Py_BuildValue(""));
+            } else {
+                dsrc.reset(wrapDataSourceClient(result.dsrc_client_));
+            }
+            PyObjectContainer finder;
+            if (result.finder_ == NULL) {
+                finder.reset(Py_BuildValue(""));
+            } else {
+                finder.reset(createZoneFinderObject(result.finder_));
+            }
+            PyObjectContainer exact(PyBool_FromLong(result.exact_match_));
+
+            return (Py_BuildValue("OOO", dsrc.get(), finder.get(),
+                                  exact.get()));
+        } else {
+            return (NULL);
+        }
+    } catch (const std::exception& exc) {
+        PyErr_SetString(getDataSourceException("Error"), exc.what());
+        return (NULL);
+    } catch (...) {
+        PyErr_SetString(getDataSourceException("Error"),
+                        "Unknown C++ exception");
+        return (NULL);
+    }
+}
+
 // This list contains the actual set of functions we have in
 // python. Each entry has
 // 1. Python method name
@@ -120,6 +166,7 @@ ConfigurableClientList_configure(PyObject* po_self, PyObject* args) {
 PyMethodDef ConfigurableClientList_methods[] = {
     { "configure", ConfigurableClientList_configure, METH_VARARGS,
         "TODO: Docs" },
+    { "find", ConfigurableClientList_find, METH_VARARGS, "TODO: Docs" },
     { NULL, NULL, 0, NULL }
 };
 } // end of unnamed namespace

+ 61 - 0
src/lib/python/isc/datasrc/tests/clientlist_test.py

@@ -52,6 +52,11 @@ class ClientListTest(unittest.TestCase):
         clist = isc.datasrc.ConfigurableClientList(isc.dns.RRClass.IN())
         # This should be NOP now
         clist.configure("[]", True)
+        # Check the zone is not there yet
+        dsrc, finder, exact = clist.find(isc.dns.Name("example.org"))
+        self.assertIsNone(dsrc)
+        self.assertIsNone(finder)
+        self.assertFalse(exact)
         # We can use this type, as it is not loaded dynamically.
         clist.configure('''[{
             "type": "MasterFiles",
@@ -60,6 +65,14 @@ class ClientListTest(unittest.TestCase):
             },
             "cache-enable": true
         }]''', True)
+        # Check the zone is there now. Proper tests of find are in other
+        # test methods.
+        dsrc, finder, exact = clist.find(isc.dns.Name("example.org"))
+        self.assertIsNotNone(dsrc)
+        self.assertTrue(isinstance(dsrc, isc.datasrc.DataSourceClient))
+        self.assertIsNotNone(finder)
+        self.assertTrue(isinstance(finder, isc.datasrc.ZoneFinder))
+        self.assertTrue(exact)
         self.assertRaises(isc.datasrc.Error, clist.configure, '"bad type"',
                           True)
         self.assertRaises(isc.datasrc.Error, clist.configure, '''[{
@@ -72,6 +85,54 @@ class ClientListTest(unittest.TestCase):
         self.assertRaises(TypeError, clist.configure, "[]")
         self.assertRaises(TypeError, clist.configure, "[]", "true")
 
+    def test_find(self):
+        """
+        Test the find accepts the right arguments, some of them can be omitted,
+        etc.
+        """
+        clist = isc.datasrc.ConfigurableClientList(isc.dns.RRClass.IN())
+        clist.configure('''[{
+            "type": "MasterFiles",
+            "params": {
+                "example.org": "''' + TESTDATA_PATH + '''example.org.zone"
+            },
+            "cache-enable": true
+        }]''', True)
+        dsrc, finder, exact = clist.find(isc.dns.Name("sub.example.org"))
+        self.assertIsNotNone(dsrc)
+        self.assertTrue(isinstance(dsrc, isc.datasrc.DataSourceClient))
+        self.assertIsNotNone(finder)
+        self.assertTrue(isinstance(finder, isc.datasrc.ZoneFinder))
+        # We check an exact match in test_configure already
+        self.assertFalse(exact)
+        dsrc, finder, exact = clist.find(isc.dns.Name("sub.example.org"),
+                                         False)
+        self.assertIsNotNone(dsrc)
+        self.assertTrue(isinstance(dsrc, isc.datasrc.DataSourceClient))
+        self.assertIsNotNone(finder)
+        self.assertTrue(isinstance(finder, isc.datasrc.ZoneFinder))
+        self.assertFalse(exact)
+        dsrc, finder, exact = clist.find(isc.dns.Name("sub.example.org"),
+                                         True)
+        self.assertIsNone(dsrc)
+        self.assertIsNone(finder)
+        self.assertFalse(exact)
+        dsrc, finder, exact = clist.find(isc.dns.Name("sub.example.org"),
+                                         False, False)
+        self.assertIsNotNone(dsrc)
+        self.assertTrue(isinstance(dsrc, isc.datasrc.DataSourceClient))
+        self.assertIsNotNone(finder)
+        self.assertTrue(isinstance(finder, isc.datasrc.ZoneFinder))
+        self.assertFalse(exact)
+        dsrc, finder, exact = clist.find(isc.dns.Name("sub.example.org"),
+                                         True, False)
+        self.assertIsNone(dsrc)
+        self.assertIsNone(finder)
+        self.assertFalse(exact)
+        # Some invalid inputs
+        self.assertRaises(TypeError, clist.find, "example.org")
+        self.assertRaises(TypeError, clist.find)
+
 if __name__ == "__main__":
     isc.log.init("bind10")
     isc.log.resetUnitTestRootLogger()