Commit 8fc9df7f authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1287] added python wrapper

parent 254eb201
......@@ -31,4 +31,37 @@ the end of the zone.\n\
Raises an isc.datasrc.Error exception if it is called again after returning\n\
// Modifications:
// - ConstRRset->RRset
// - NULL->None
// - removed notes about derived classes (which doesn't apply for python)
const char* const ZoneIterator_getSOA_doc = "\
get_soa() -> isc.dns.RRset\n\
Return the SOA record of the zone in the iterator context.\n\
This method returns the zone's SOA record (if any, and a valid zone\n\
should have it) in the form of an RRset object. This SOA is identical\n\
to that (again, if any) contained in the sequence of RRsets returned\n\
by the iterator. In that sense this method is redundant, but is\n\
provided as a convenient utility for the application of the iterator;\n\
the application may need to know the SOA serial or the SOA RR itself\n\
for the purpose of protocol handling or skipping the expensive\n\
iteration processing.\n\
If the zone doesn't have an SOA (which is broken, but some data source\n\
may allow that situation), this method returns None. Also, in the\n\
normal and valid case, the SOA should have exactly one RDATA, but this\n\
API is not guaranteed it as some data source may accept such an\n\
abnormal condition. It's up to the caller whether to check the number\n\
of RDATA and how to react to the unexpected case.\n\
Return Value(s): An SOA RRset object that would be\n\
returned from the iteration. It will be None if the zone doesn't have\n\
an SOA.\n\
} // unnamed namespace
......@@ -132,10 +132,35 @@ ZoneIterator_next(PyObject* self) {
ZoneIterator_getSOA(PyObject* po_self, PyObject*) {
s_ZoneIterator* self = static_cast<s_ZoneIterator*>(po_self);
try {
isc::dns::ConstRRsetPtr rrset = self->cppobj->getSOA();
if (!rrset) {
return (createRRsetObject(*rrset));
} catch (const isc::Exception& isce) {
// isc::Unexpected is thrown when we call getNextRRset() when we are
// already done iterating ('iterating past end')
// We could also simply return None again
PyErr_SetString(getDataSourceException("Error"), isce.what());
return (NULL);
} catch (const std::exception& exc) {
PyErr_SetString(getDataSourceException("Error"), exc.what());
return (NULL);
} catch (...) {
"Unexpected exception");
return (NULL);
PyMethodDef ZoneIterator_methods[] = {
{ "get_next_rrset",
reinterpret_cast<PyCFunction>(ZoneIterator_getNextRRset), METH_NOARGS,
{ "get_next_rrset", ZoneIterator_getNextRRset, METH_NOARGS,
ZoneIterator_getNextRRset_doc },
{ "get_soa", ZoneIterator_getSOA, METH_NOARGS, ZoneIterator_getSOA_doc },
......@@ -189,6 +189,20 @@ class DataSrcClient(unittest.TestCase):
self.assertRaises(TypeError, dsc.get_iterator, "asdf")
def test_iterator_soa(self):
dsc = isc.datasrc.DataSourceClient("sqlite3", READ_ZONE_DB_CONFIG)
iterator = dsc.get_iterator(isc.dns.Name(""))
expected_soa = isc.dns.RRset(isc.dns.Name(""),
" " +
" 678 " +
"3600 1800 2419200 7200"))
self.assertTrue(rrsets_equal(expected_soa, iterator.get_soa()))
def test_construct(self):
# can't construct directly
self.assertRaises(TypeError, isc.datasrc.ZoneFinder)
......@@ -512,6 +526,17 @@ class DataSrcUpdater(unittest.TestCase):
dsc.get_updater(isc.dns.Name(""), True)
self.assertEqual(orig_ref, sys.getrefcount(dsc))
def test_iterate_over_empty_zone(self):
# empty the test zone first
dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
updater = dsc.get_updater(isc.dns.Name(""), True)
# Check the iterator behavior for the empty zone.
iterator = dsc.get_iterator(isc.dns.Name(""))
self.assertEqual(None, iterator.get_soa())
self.assertEqual(None, iterator.get_next_rrset())
if __name__ == "__main__":
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment