[svn] commit: r2859 - in /branches/trac232/src/lib/datasrc/python: libdata_source_python.cc tests/data_source_python_test.py
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Sep 8 10:18:41 UTC 2010
Author: jelte
Date: Wed Sep 8 10:18:41 2010
New Revision: 2859
Log:
findRRset()
also added a number of conversion functions, which should probably be moved to a more general location
Modified:
branches/trac232/src/lib/datasrc/python/libdata_source_python.cc
branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py
Modified: branches/trac232/src/lib/datasrc/python/libdata_source_python.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/python/libdata_source_python.cc (original)
+++ branches/trac232/src/lib/datasrc/python/libdata_source_python.cc Wed Sep 8 10:18:41 2010
@@ -22,6 +22,10 @@
#include <datasrc/data_source.h>
#include <datasrc/sqlite3_datasrc.h>
+#include <dns/rrsetlist.h>
+#include <dns/rrset.h>
+
+#include <boost/foreach.hpp>
using namespace isc::datasrc;
@@ -69,6 +73,7 @@
static PyObject* DataSrc_getClass(s_DataSrc* self);
static PyObject* DataSrc_init(s_DataSrc* self, PyObject *args);
static PyObject* DataSrc_close(s_DataSrc* self);
+static PyObject* DataSrc_findRRset(s_DataSrc* self, PyObject* args);
static PyObject* DataSrc_startTransaction(s_DataSrc* self, PyObject* args);
static PyObject* DataSrc_commitTransaction(s_DataSrc* self, PyObject* args);
static PyObject* DataSrc_rollbackTransaction(s_DataSrc* self, PyObject* args);
@@ -80,6 +85,8 @@
"Initializes the data source" },
{ "close", reinterpret_cast<PyCFunction>(DataSrc_close), METH_NOARGS,
"Closes the data source" },
+ { "find_rrset", reinterpret_cast<PyCFunction>(DataSrc_findRRset), METH_VARARGS,
+ "Searches the datasource for an RRset" },
{ "start_transaction", reinterpret_cast<PyCFunction>(DataSrc_startTransaction), METH_VARARGS,
"Start a transaction" },
{ "commit_transaction", reinterpret_cast<PyCFunction>(DataSrc_commitTransaction), METH_VARARGS,
@@ -244,6 +251,160 @@
Py_TYPE(self)->tp_free(self);
}
+/* conversion functions, also usable by other modules
+ * (TODO: move to separate file)
+ */
+isc::dns::Name
+pyName_AsName(PyObject* name_obj)
+{
+ PyObject* name_obj_str = PyObject_CallMethod(name_obj, "to_text", NULL);
+ const char* name_str = PyBytes_AS_STRING(PyUnicode_AsUTF8String(name_obj_str));
+ return isc::dns::Name(name_str);
+}
+
+// do we need this one?
+/*
+const char *
+pyName_AsString(PyObject* name_obj)
+{
+ PyObject* name_obj_str = PyObject_CallMethod(name_obj, "to_text", NULL);
+ return PyBytes_AS_STRING(PyUnicode_AsUTF8String(name_obj_str));
+}
+*/
+
+PyObject*
+pyName_FromString(const char* name_str)
+{
+ PyObject* name_class = PyObject_GetAttrString(po_DNS_module, "Name");
+ PyObject* name = PyObject_CallObject(name_class, Py_BuildValue("(s)", name_str));
+ Py_DECREF(name_class);
+ return name;
+}
+
+PyObject*
+pyName_FromName(const isc::dns::Name& name)
+{
+ return pyName_FromString(name.toText().c_str());
+}
+
+isc::dns::RRClass
+pyRRClass_AsRRClass(PyObject* rrclass_obj)
+{
+ PyObject* rrclass_obj_str = PyObject_CallMethod(rrclass_obj, "to_text", NULL);
+ const char* rrclass_str = PyBytes_AS_STRING(PyUnicode_AsUTF8String(rrclass_obj_str));
+ return isc::dns::RRClass(rrclass_str);
+}
+
+PyObject*
+pyRRClass_FromString(const char* rrclass_str)
+{
+ PyObject* rrclass_class = PyObject_GetAttrString(po_DNS_module, "RRClass");
+ PyObject* rrclass = PyObject_CallObject(rrclass_class, Py_BuildValue("(s)", rrclass_str));
+ Py_DECREF(rrclass_class);
+ return rrclass;
+}
+
+PyObject*
+pyRRClass_FromRRClass(const isc::dns::RRClass& rrclass)
+{
+ return pyRRClass_FromString(rrclass.toText().c_str());
+}
+
+PyObject*
+pyRRType_FromString(const char* rrtype_str)
+{
+ PyObject* rrtype_class = PyObject_GetAttrString(po_DNS_module, "RRType");
+ PyObject* rrtype = PyObject_CallObject(rrtype_class, Py_BuildValue("(s)", rrtype_str));
+ Py_DECREF(rrtype_class);
+ return rrtype;
+}
+
+PyObject*
+pyRRType_FromRRType(const isc::dns::RRType& rrtype)
+{
+ return pyRRType_FromString(rrtype.toText().c_str());
+}
+
+isc::dns::RRType
+pyRRType_AsRRType(PyObject* rrtype_obj)
+{
+ PyObject* rrtype_obj_str = PyObject_CallMethod(rrtype_obj, "to_text", NULL);
+ const char* rrtype_str = PyBytes_AS_STRING(PyUnicode_AsUTF8String(rrtype_obj_str));
+ return isc::dns::RRType(rrtype_str);
+}
+
+PyObject*
+pyRRTTL_FromString(const char* rrttl_str)
+{
+ PyObject* rrttl_class = PyObject_GetAttrString(po_DNS_module, "RRTTL");
+ PyObject* rrttl = PyObject_CallObject(rrttl_class, Py_BuildValue("(s)", rrttl_str));
+ Py_DECREF(rrttl_class);
+ return rrttl;
+}
+
+PyObject*
+pyRRTTL_FromRRTTL(const isc::dns::RRTTL& rrttl)
+{
+ return pyRRTTL_FromString(rrttl.toText().c_str());
+}
+
+isc::dns::RRTTL
+pyRRTTL_AsRRTTL(PyObject* rrttl_obj)
+{
+ PyObject* rrttl_obj_str = PyObject_CallMethod(rrttl_obj, "to_text", NULL);
+ const char* rrttl_str = PyBytes_AS_STRING(PyUnicode_AsUTF8String(rrttl_obj_str));
+ return isc::dns::RRTTL(rrttl_str);
+}
+
+PyObject*
+pyRdata_createRdata(const isc::dns::RRType& rrtype, const isc::dns::RRClass& rrclass, const isc::dns::rdata::Rdata& rdata) {
+ PyObject* rdata_class = PyObject_GetAttrString(po_DNS_module, "Rdata");
+ PyObject* type_obj = pyRRType_FromRRType(rrtype);
+ PyObject* class_obj = pyRRClass_FromRRClass(rrclass);
+ PyObject* rdata_obj = PyObject_CallObject(rdata_class,
+ Py_BuildValue("(OOs)",
+ type_obj,
+ class_obj,
+ rdata.toText().c_str()));
+ Py_DECREF(rdata_class);
+ Py_DECREF(type_obj);
+ Py_DECREF(class_obj);
+ return rdata_obj;
+}
+
+PyObject*
+pyRRset_FromRRset(const isc::dns::RRset& rrset)
+{
+ PyObject* rrset_class = PyObject_GetAttrString(po_DNS_module, "RRset");
+ PyObject* name_obj = pyName_FromName(rrset.getName());
+ PyObject* rrclass_obj = pyRRClass_FromRRClass(rrset.getClass());
+ PyObject* rrtype_obj = pyRRType_FromRRType(rrset.getType());
+ PyObject* rrttl_obj = pyRRTTL_FromRRTTL(rrset.getTTL());
+
+ PyObject* rrset_obj = PyObject_CallObject(rrset_class,
+ Py_BuildValue("OOOO",
+ name_obj,
+ rrclass_obj,
+ rrtype_obj,
+ rrttl_obj));
+
+ Py_DECREF(rrset_class);
+ Py_DECREF(name_obj);
+ Py_DECREF(rrclass_obj);
+ Py_DECREF(rrtype_obj);
+ Py_DECREF(rrttl_obj);
+
+ isc::dns::RdataIteratorPtr it = rrset.getRdataIterator();
+ for (it->first(); !it->isLast(); it->next()) {
+ PyObject* rdata_obj = pyRdata_createRdata(rrset.getType(), rrset.getClass(), it->getCurrent());
+ PyObject_CallMethod(rrset_obj, "add_rdata", "O", rdata_obj);
+ Py_DECREF(rdata_obj);
+ }
+ return rrset_obj;
+}
+
+/* end of conversion functions */
+
static PyObject*
DataSrc_init(s_DataSrc* self, PyObject* args)
{
@@ -278,6 +439,51 @@
return (Py_BuildValue("I", self->datasrc->close()));
} catch (DataSourceError dse) {
PyErr_SetString(po_DataSrcError, dse.what());
+ return (NULL);
+ }
+}
+
+static PyObject*
+DataSrc_findRRset(s_DataSrc* self, PyObject* args) {
+ PyObject* name_class = PyObject_GetAttrString(po_DNS_module, "Name");
+ PyObject* rrclass_class = PyObject_GetAttrString(po_DNS_module, "RRClass");
+ PyObject* rrtype_class = PyObject_GetAttrString(po_DNS_module, "RRType");
+ PyObject *name_obj, *class_obj, *type_obj, *result_list_obj, *zone_name_obj;
+ uint32_t flags;
+ int args_check = PyArg_ParseTuple(args, "O!O!O!OIO!",
+ name_class, &name_obj,
+ rrclass_class, &class_obj,
+ rrtype_class, &type_obj,
+ &result_list_obj,
+ &flags,
+ name_class, &zone_name_obj);
+ Py_DECREF(name_class);
+ Py_DECREF(rrclass_class);
+ Py_DECREF(rrtype_class);
+
+ if (args_check) {
+ if (!PyList_Check(result_list_obj)) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 4 of find_rrset is not a List");
+ return (NULL);
+ }
+ isc::dns::Name n = pyName_AsName(name_obj);
+ isc::dns::RRClass c = pyRRClass_AsRRClass(class_obj);
+ isc::dns::RRType t = pyRRType_AsRRType(type_obj);
+ isc::dns::Name zone_name = pyName_AsName(zone_name_obj);
+
+ isc::dns::RRsetList result_list;
+ isc::datasrc::DataSrc::Result result =
+ self->datasrc->findRRset(n, c, t, result_list,
+ flags, &zone_name);
+
+ BOOST_FOREACH(isc::dns::RRsetPtr rrs, result_list) {
+ PyObject *rrset_obj = pyRRset_FromRRset(*rrs);
+ PyList_Append(result_list_obj, rrset_obj);
+ Py_DECREF(rrset_obj);
+ }
+ return Py_BuildValue("I", result);
+ } else {
return (NULL);
}
}
Modified: branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py
==============================================================================
--- branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py (original)
+++ branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py Wed Sep 8 10:18:41 2010
@@ -21,42 +21,91 @@
import sys
import os
from libdata_source_python import *
-from libdns_python import Name, RRClass
+from libdns_python import *
class DataSourceTest(unittest.TestCase):
+ def setUp(self):
+ self.ds = DataSrc()
+
def test_init_close(self):
- ds = DataSrc()
- self.assertRaises(DataSrcError, ds.close)
- self.assertRaises(TypeError, ds.close, 1)
+ self.assertRaises(DataSrcError, self.ds.close)
+ self.assertRaises(TypeError, self.ds.close, 1)
print(testdata_path)
- self.assertRaises(DataSrcError, ds.init, 1)
- self.assertRaises(DataSrcError, ds.init, "{")
- self.assertRaises(DataSrcError, ds.init, "{ \"database_file\": \"/ badfilename /\" }")
- self.assertRaises(DataSrcError, ds.init, "{ \"database_file\": \"/brokendb.sqlite3\" }")
- ds.init("{ \"database_file\": \""+ testdata_path + "/example2.com.sqlite3\" }")
- self.assertEqual(0, ds.close())
+ self.assertRaises(DataSrcError, self.ds.init, 1)
+ self.assertRaises(DataSrcError, self.ds.init, "{")
+ self.assertRaises(DataSrcError, self.ds.init, "{ \"database_file\": \"/ badfilename /\" }")
+ self.assertRaises(DataSrcError, self.ds.init, "{ \"database_file\": \"/brokendb.sqlite3\" }")
+ self.ds.init("{ \"database_file\": \""+ testdata_path + "/example.org.sqlite3\" }")
+ self.assertEqual(0, self.ds.close())
def test_get_class(self):
- ds = DataSrc()
- self.assertEqual(RRClass("IN"), ds.get_class())
+ self.assertEqual(RRClass("IN"), self.ds.get_class())
+
+ def test_find_rrset(self):
+ self.ds.init("{ \"database_file\": \""+ testdata_path + "/example.org.sqlite3\" }")
+ result = []
+ n = self.ds.find_rrset(Name("www.example.org"), RRClass.IN(), RRType.A(), result, 0, Name("example.org"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(1, len(result))
+ self.assertEqual("www.example.org. 3600 IN A 192.0.2.1\n", str(result[0]))
+
+ result = []
+ n = self.ds.find_rrset(Name("doesnotexist.example.org"), RRClass.IN(), RRType.A(), result, 0, Name("example.org"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(0, len(result))
+
+ result = []
+ n = self.ds.find_rrset(Name("www.doesnotexist.org"), RRClass.IN(), RRType.A(), result, 0, Name("doesnotexist.org"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(0, len(result))
+
+ self.assertRaises(TypeError, self.ds.find_rrset);
+ self.assertRaises(TypeError, self.ds.find_rrset,
+ Name("www.doesnotexist.org"),
+ RRClass.IN(), RRType.A(), 0,
+ 0, Name("doesnotexist.org"));
+
+class DataSourceWriteTest(unittest.TestCase):
+ def setUp(self):
+ install_writable_database()
+ self.ds = DataSrc()
+ self.ds.init("{ \"database_file\": \""+ testdata_out_path + "/write_test.sqlite3\" }")
def test_transaction(self):
- install_writable_database()
- ds = DataSrc()
- ds.init("{ \"database_file\": \""+ testdata_out_path + "/write_test.sqlite3\" }")
+ self.assertRaises(TypeError, self.ds.start_transaction)
+ self.assertRaises(TypeError, self.ds.start_transaction, 1)
+ self.assertRaises(TypeError, self.ds.start_transaction, 1, RRClass.IN())
+ self.assertRaises(TypeError, self.ds.start_transaction, Name("example.com"), 1)
+
+ transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+ self.assertEqual(DataSrcTransaction.INIT, transaction.get_state())
+
+ result = self.ds.start_transaction(transaction)
+ self.assertEqual(DataSrc.T_SUCCESS, result)
+ self.assertEqual(DataSrcTransaction.RUNNING, transaction.get_state())
+
+ self.ds.rollback_transaction(transaction)
+ self.assertEqual(DataSrcTransaction.DONE, transaction.get_state())
+
+ transaction = DataSrcTransaction(self.ds, Name("doesnotexist.com"), RRClass.IN())
+ result = self.ds.start_transaction(transaction)
+ self.assertEqual(DataSrc.T_NO_SUCH_ZONE, result)
+ self.assertEqual(DataSrcTransaction.INIT, transaction.get_state())
+
+ def test_add_rrset(self):
+ rrset = RRset(Name("pythontest.example.com"), RRClass.IN(), RRType.A(), RRTTL(3600))
- self.assertRaises(TypeError, ds.start_transaction)
- self.assertRaises(TypeError, ds.start_transaction, 1)
+ transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+ self.assertEqual(DataSrcTransaction.INIT, transaction.get_state())
- transaction1 = DataSrcTransaction(ds, Name("example.com"), RRClass.IN())
- self.assertEqual(DataSrcTransaction.INIT, transaction1.get_state())
+ result = self.ds.start_transaction(transaction)
+ self.assertEqual(DataSrc.T_SUCCESS, result)
- ds.start_transaction(transaction1)
- self.assertEqual(DataSrcTransaction.RUNNING, transaction1.get_state())
+ #result = self.ds.add_rrset(transaction, rrset)
+ self.assertEqual(DataSrc.T_SUCCESS, result)
- ds.rollback_transaction(transaction1)
- self.assertEqual(DataSrcTransaction.DONE, transaction1.get_state())
+ self.ds.rollback_transaction(transaction)
# helper functions for tests taken from c++ unittests
More information about the bind10-changes
mailing list