Commit d1a1871c authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[1179] python wrapper for new datasrc classes

parent af10f1ef
......@@ -834,6 +834,7 @@ AC_CONFIG_FILES([Makefile
src/lib/python/isc/util/tests/Makefile
src/lib/python/isc/datasrc/Makefile
src/lib/python/isc/datasrc/tests/Makefile
src/lib/python/isc/dns/Makefile
src/lib/python/isc/cc/Makefile
src/lib/python/isc/cc/tests/Makefile
src/lib/python/isc/config/Makefile
......
SUBDIRS = exceptions util log cryptolink dns cc config acl python xfr \
bench asiolink asiodns nsas cache resolve testutils datasrc \
server_common
SUBDIRS = exceptions util log cryptolink dns cc config acl xfr bench \
asiolink asiodns nsas cache resolve testutils datasrc \
server_common python
SUBDIRS = datasrc cc config log net notify util testutils acl bind10
SUBDIRS = datasrc cc config dns log net notify util testutils acl bind10
python_PYTHON = __init__.py
......
SUBDIRS = . tests
# old data, should be removed in the near future once conversion is done
python_PYTHON = __init__.py master.py sqlite3_ds.py
pythondir = $(pyexecdir)/isc/datasrc
#pythondir = $(pyexecdir)/isc/pydatasrc
# new data
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(SQLITE_CFLAGS)
pythondir = $(pyexecdir)/isc
pyexec_LTLIBRARIES = datasrc.la
datasrc_la_SOURCES = datasrc.cc datasrc.h
datasrc_la_SOURCES += client_python.cc client_python.h
datasrc_la_SOURCES += iterator_python.cc iterator_python.h
datasrc_la_SOURCES += finder_python.cc finder_python.h
datasrc_la_SOURCES += updater_python.cc updater_python.h
datasrc_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
datasrc_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
datasrc_la_LDFLAGS = $(PYTHON_LDFLAGS)
datasrc_la_LDFLAGS += -module
datasrc_la_LIBADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
datasrc_la_LIBADD += $(top_builddir)/src/lib/dns/python/libpydnspp.la
datasrc_la_LIBADD += $(PYTHON_LIB)
datasrc_la_LIBADD += $(SQLITE_LIBS)
CLEANDIRS = __pycache__
clean-local:
rm -rf $(CLEANDIRS)
from isc.datasrc.master import *
from isc.datasrc.sqlite3_ds import *
for base in sys.path[:]:
loglibdir = os.path.join(base, 'isc/datasrc/.libs')
if os.path.exists(loglibdir):
sys.path.insert(0, loglibdir)
from datasrc import *
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// Enable this if you use s# variants with PyArg_ParseTuple(), see
// http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
//#define PY_SSIZE_T_CLEAN
// Python.h needs to be placed at the head of the program file, see:
// http://docs.python.org/py3k/extending/extending.html#a-simple-example
#include <Python.h>
#include <string>
#include <stdexcept>
#include <util/python/pycppwrapper_util.h>
#include <datasrc/client.h>
#include <datasrc/database.h>
#include <datasrc/sqlite3_accessor.h>
#include <datasrc/iterator.h>
#include <dns/python/name_python.h>
#include <dns/python/rrset_python.h>
#include <dns/python/pydnspp_common.h>
#include "datasrc.h"
#include "client_python.h"
#include "finder_python.h"
#include "iterator_python.h"
#include "updater_python.h"
using namespace std;
using namespace isc::util::python;
using namespace isc::datasrc;
using namespace isc::datasrc::python;
//
// Definition of the classes
//
// For each class, we need a struct, a helper functions (init, destroy,
// and static wrappers around the methods we export), a list of methods,
// and a type description
//
// DataSourceClient
//
// Trivial constructor.
s_DataSourceClient::s_DataSourceClient() : cppobj(NULL) {
}
namespace {
// Shortcut type which would be convenient for adding class variables safely.
typedef CPPPyObjectContainer<s_DataSourceClient, DataSourceClient>
DataSourceClientContainer;
//
// We declare the functions here, the definitions are below
// the type definition of the object, since both can use the other
//
// General creation and destruction
int DataSourceClient_init(s_DataSourceClient* self, PyObject* args);
void DataSourceClient_destroy(s_DataSourceClient* self);
// These are the functions we export
//
PyObject*
DataSourceClient_FindZone(PyObject* po_self, PyObject* args) {
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
PyObject *name;
if (PyArg_ParseTuple(args, "O!", &isc::dns::python::name_type, &name)) {
DataSourceClient::FindResult find_result(
self->cppobj->findZone(isc::dns::python::PyName_ToName(name)));
result::Result r = find_result.code;
ZoneFinderPtr zfp = find_result.zone_finder;
return Py_BuildValue("IO", r, createZoneFinderObject(zfp));
} else {
return (NULL);
}
}
PyObject*
DataSourceClient_GetIterator(PyObject* po_self, PyObject* args) {
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
PyObject *name_obj;
if (PyArg_ParseTuple(args, "O!", &isc::dns::python::name_type, &name_obj)) {
return (createZoneIteratorObject(self->cppobj->getIterator(isc::dns::python::PyName_ToName(name_obj))));
} else {
return (NULL);
}
}
PyObject*
DataSourceClient_GetUpdater(PyObject* po_self, PyObject* args) {
s_DataSourceClient* const self = static_cast<s_DataSourceClient*>(po_self);
PyObject *name_obj;
PyObject *replace_obj;
if (PyArg_ParseTuple(args, "O!O", &isc::dns::python::name_type, &name_obj, &replace_obj) && PyBool_Check(replace_obj)) {
bool replace = (replace_obj != Py_False);
return (createZoneUpdaterObject(self->cppobj->getUpdater(isc::dns::python::PyName_ToName(name_obj), replace)));
} else {
return (NULL);
}
}
// These are the functions we export
// This list contains the actual set of functions we have in
// python. Each entry has
// 1. Python method name
// 2. Our static function here
// 3. Argument type
// 4. Documentation
PyMethodDef DataSourceClient_methods[] = {
{ "find_zone", DataSourceClient_FindZone, METH_VARARGS, "TODO" },
{ "get_iterator", DataSourceClient_GetIterator, METH_VARARGS, "TODO" },
{ "get_updater", DataSourceClient_GetUpdater, METH_VARARGS, "TODO" },
{ NULL, NULL, 0, NULL }
};
// This is a template of typical code logic of python class initialization
// with C++ backend. You'll need to adjust it according to details of the
// actual C++ class.
int
DataSourceClient_init(s_DataSourceClient* self, PyObject* args) {
// TODO: we should use the factory function which hasn't been written
// yet. For now we hardcode the sqlite3 initialization, and pass it one
// string for the database file. (similar to how the 'old direct'
// sqlite3_ds code works)
try {
char* db_file_name;
if (PyArg_ParseTuple(args, "s", &db_file_name)) {
boost::shared_ptr<DatabaseAccessor> sqlite3_accessor(
new SQLite3Accessor(db_file_name, isc::dns::RRClass::IN()));
self->cppobj = new DatabaseClient(isc::dns::RRClass::IN(),
sqlite3_accessor);
return (0);
} else {
return (-1);
}
} catch (const exception& ex) {
const string ex_what = "Failed to construct DataSourceClient object: " +
string(ex.what());
PyErr_SetString(getDataSourceException("Error"), ex_what.c_str());
return (-1);
} catch (...) {
PyErr_SetString(PyExc_RuntimeError,
"Unexpected exception in constructing DataSourceClient");
return (-1);
}
PyErr_SetString(PyExc_TypeError,
"Invalid arguments to DataSourceClient constructor");
return (-1);
}
// This is a template of typical code logic of python object destructor.
// In many cases you can use it without modification, but check that carefully.
void
DataSourceClient_destroy(s_DataSourceClient* const self) {
delete self->cppobj;
self->cppobj = NULL;
Py_TYPE(self)->tp_free(self);
}
} // end anonymous namespace
namespace isc {
namespace datasrc {
namespace python {
// This defines the complete type for reflection in python and
// parsing of PyObject* to s_DataSourceClient
// Most of the functions are not actually implemented and NULL here.
PyTypeObject datasourceclient_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"datasrc.DataSourceClient",
sizeof(s_DataSourceClient), // tp_basicsize
0, // tp_itemsize
reinterpret_cast<destructor>(DataSourceClient_destroy), // tp_dealloc
NULL, // tp_print
NULL, // tp_getattr
NULL, // tp_setattr
NULL, // tp_reserved
NULL, // tp_repr
NULL, // tp_as_number
NULL, // tp_as_sequence
NULL, // tp_as_mapping
NULL, // tp_hash
NULL, // tp_call
NULL, // tp_str
NULL, // tp_getattro
NULL, // tp_setattro
NULL, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"The DataSourceClient class objects is...(COMPLETE THIS)",
NULL, // tp_traverse
NULL, // tp_clear
NULL, // tp_richcompare
0, // tp_weaklistoffset
NULL, // tp_iter
NULL, // tp_iternext
DataSourceClient_methods, // tp_methods
NULL, // tp_members
NULL, // tp_getset
NULL, // tp_base
NULL, // tp_dict
NULL, // tp_descr_get
NULL, // tp_descr_set
0, // tp_dictoffset
reinterpret_cast<initproc>(DataSourceClient_init), // tp_init
NULL, // tp_alloc
PyType_GenericNew, // tp_new
NULL, // tp_free
NULL, // tp_is_gc
NULL, // tp_bases
NULL, // tp_mro
NULL, // tp_cache
NULL, // tp_subclasses
NULL, // tp_weaklist
NULL, // tp_del
0 // tp_version_tag
};
// Module Initialization, all statics are initialized here
bool
initModulePart_DataSourceClient(PyObject* mod) {
// We initialize the static description object with PyType_Ready(),
// then add it to the module. This is not just a check! (leaving
// this out results in segmentation faults)
if (PyType_Ready(&datasourceclient_type) < 0) {
return (false);
}
void* dscp = &datasourceclient_type;
if (PyModule_AddObject(mod, "DataSourceClient", static_cast<PyObject*>(dscp)) < 0) {
return (false);
}
Py_INCREF(&datasourceclient_type);
isc::dns::python::addClassVariable(datasourceclient_type, "SUCCESS",
Py_BuildValue("I", result::SUCCESS));
isc::dns::python::addClassVariable(datasourceclient_type, "EXIST",
Py_BuildValue("I", result::EXIST));
isc::dns::python::addClassVariable(datasourceclient_type, "NOTFOUND",
Py_BuildValue("I", result::NOTFOUND));
isc::dns::python::addClassVariable(datasourceclient_type, "PARTIALMATCH",
Py_BuildValue("I", result::PARTIALMATCH));
return (true);
}
} // namespace python
} // namespace datasrc
} // namespace isc
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __PYTHON_DATASRC_CLIENT_H
#define __PYTHON_DATASRC_CLIENT_H 1
#include <Python.h>
namespace isc {
namespace datasrc {
class DataSourceClient;
namespace python {
// The s_* Class simply covers one instantiation of the object
class s_DataSourceClient : public PyObject {
public:
s_DataSourceClient();
DataSourceClient* cppobj;
};
extern PyTypeObject datasourceclient_type;
bool initModulePart_DataSourceClient(PyObject* mod);
} // namespace python
} // namespace datasrc
} // namespace isc
#endif // __PYTHON_DATASRC_CLIENT_H
// Local Variables:
// mode: c++
// End:
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>
#include <config.h>
#include <datasrc/client.h>
#include <datasrc/database.h>
#include <datasrc/sqlite3_accessor.h>
#include "datasrc.h"
#include "client_python.h"
#include "finder_python.h"
#include "iterator_python.h"
#include "updater_python.h"
#include <util/python/pycppwrapper_util.h>
using namespace isc::datasrc::python;
using namespace isc::util::python;
namespace isc {
namespace datasrc {
namespace python {
PyObject*
getDataSourceException(const char* ex_name) {
PyObject* ex_obj = NULL;
PyObject* acl_module = PyImport_AddModule("isc.datasrc");
if (acl_module != NULL) {
PyObject* acl_dict = PyModule_GetDict(acl_module);
if (acl_dict != NULL) {
ex_obj = PyDict_GetItemString(acl_dict, ex_name);
}
}
if (ex_obj == NULL) {
ex_obj = PyExc_RuntimeError;
}
return (ex_obj);
}
} // end namespace python
} // end namespace datasrc
} // end namespace isc
namespace {
PyObject* po_DataSourceError;
PyModuleDef iscDataSrc = {
{ PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
"datasrc",
"Python bindings for the classes in the isc::datasrc namespace.\n\n"
"These bindings are close match to the C++ API, but they are not complete "
"(some parts are not needed) and some are done in more python-like ways.",
-1,
NULL,// TODO do we need module-level functions?
NULL,
NULL,
NULL,
NULL
};
} // end anonymous namespace
PyMODINIT_FUNC
PyInit_datasrc(void) {
PyObject* mod = PyModule_Create(&iscDataSrc);
if (mod == NULL) {
return (NULL);
}
if (!initModulePart_DataSourceClient(mod)) {
Py_DECREF(mod);
return (NULL);
}
if (!initModulePart_ZoneFinder(mod)) {
Py_DECREF(mod);
return (NULL);
}
if (!initModulePart_ZoneIterator(mod)) {
Py_DECREF(mod);
return (NULL);
}
if (!initModulePart_ZoneUpdater(mod)) {
Py_DECREF(mod);
return (NULL);
}
try {
po_DataSourceError = PyErr_NewException("isc.datasrc.Error", NULL,
NULL);
PyObjectContainer(po_DataSourceError).installToModule(mod, "Error");
} catch (...) {
Py_DECREF(mod);
return (NULL);
}
return (mod);
}
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __PYTHON_DATASRC_H
#define __PYTHON_DATASRC_H 1
#include <Python.h>
namespace isc {
namespace datasrc {
namespace python {
// Return a Python exception object of the given name (ex_name) defined in
// the isc.datasrc.datasrc loadable module.
//
// Since the datasrc module is a different binary image and is loaded separately
// from the dns module, it would be very tricky to directly access to
// C/C++ symbols defined in that module. So we get access to these object
// using the Python interpretor through this wrapper function.
//
// The __init__.py file should ensure isc.acl.acl has been loaded by the time
// whenever this function is called, and there shouldn't be any operation
// within this function that can fail (such as dynamic memory allocation),
// so this function should always succeed. Yet there may be an overlooked
// failure mode, perhaps due to a bug in the binding implementation, or
// due to invalid usage. As a last resort for such cases, this function
// returns PyExc_RuntimeError (a C binding of Python's RuntimeError) should
// it encounters an unexpected failure.
extern PyObject* getDataSourceException(const char* ex_name);
} // namespace python
} // namespace datasrc
} // namespace isc
#endif // __PYTHON_ACL_DNS_H
// Local Variables:
// mode: c++
// End:
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// Enable this if you use s# variants with PyArg_ParseTuple(), see
// http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
//#define PY_SSIZE_T_CLEAN
// Python.h needs to be placed at the head of the program file, see:
// http://docs.python.org/py3k/extending/extending.html#a-simple-example
#include <Python.h>
#include <string>
#include <stdexcept>
#include <util/python/pycppwrapper_util.h>
#include <datasrc/client.h>
#include <datasrc/database.h>
#include <datasrc/sqlite3_accessor.h>
#include <datasrc/iterator.h>
#include <datasrc/zone.h>
#include <dns/python/name_python.h>
#include <dns/python/rrset_python.h>
#include <dns/python/rrclass_python.h>
#include <dns/python/rrtype_python.h>
#include <dns/python/pydnspp_common.h>
#include "datasrc.h"
#include "finder_python.h"
using namespace std;
using namespace isc::util::python;
using namespace isc::datasrc;
using namespace isc::datasrc::python;
//
// Definition of the classes
//
// For each class, we need a struct, a helper functions (init, destroy,
// and static wrappers around the methods we export), a list of methods,
// and a type description
//
// Zone Finder
//