Parcourir la source

[3413] Several build steps no longer require python3

 - *.spec files in src/lib/dns/tests/testsdata are now included in dist
 - src/lib/util/pyunittests is removed
 - src/lib/util/python trimmed down a lot
 - fix for missing dhcp6_shutdown_test.sh in src/bin/dhcp6
 - many python macros in configure.ac removed
   (more of them to be removed in Makefiles)
Tomek Mrugalski il y a 11 ans
Parent
commit
a288439190

+ 0 - 162
configure.ac

@@ -321,141 +321,6 @@ else
 	AC_SUBST(pkgpyexecdir)
 fi
 
-# We need to store the default pyexecdir in a separate variable so that
-# we can specify in Makefile.am the install directory of various BIND 10
-# python scripts and loadable modules; in Makefile.am we cannot replace
-# $(pyexecdir) using itself, e.g, this doesn't work:
-# pyexecdir = $(pyexecdir)/isc/some_module
-# The separate variable makes this setup possible as follows:
-# pyexecdir = $(PYTHON_SITEPKG_DIR)/isc/some_module
-PYTHON_SITEPKG_DIR=${pyexecdir}
-AC_SUBST(PYTHON_SITEPKG_DIR)
-
-# This will be commonly used in various Makefile.am's that need to generate
-# python log messages.
-PYTHON_LOGMSGPKG_DIR="\$(top_builddir)/src/lib/python/isc/log_messages"
-AC_SUBST(PYTHON_LOGMSGPKG_DIR)
-
-# This is python package paths commonly used in python tests.  See
-# README of log_messages for why it's included.
-# lib/dns/python/.libs is necessary because __init__.py of isc package
-# automatically imports isc.datasrc, which then requires the DNS loadable
-# module.  #2145 should eliminate the need for it.
-COMMON_PYTHON_PATH="\$(abs_top_builddir)/src/lib/python/isc/log_messages:\$(abs_top_builddir)/src/lib/python/isc/cc:\$(abs_top_srcdir)/src/lib/python:\$(abs_top_builddir)/src/lib/python:\$(abs_top_builddir)/src/lib/dns/python/.libs"
-AC_SUBST(COMMON_PYTHON_PATH)
-
-# Check for python development environments
-if test -x ${PYTHON}-config; then
-	PYTHON_INCLUDES=`${PYTHON}-config --includes`
-
-	# Add any '-L..." flags to PYTHON_LDFLAGS.  We first make a copy of
-	# python-config --ldflags, removing any spaces and tabs
-	# between "-L" and its argument (some instances of python-config
-	# insert a space, which would confuse the code below).
-	# Notes: if -L isn't contained at all we can simply skip this process,
-	# so we only go through the flag if it's contained; also, protecting
-	# the output with [] seems necessary for environment to avoid getting
-	# an empty output accidentally.
-	python_config_ldflags=[`${PYTHON}-config --ldflags | ${SED} -ne 's/\([ \t]*-L\)[ ]*\([^ \t]*[ \t]*\)/\1\2/gp'`]
-	for flag in $python_config_ldflags; do
-		flag=`echo $flag | ${SED} -ne 's/^\(\-L.*\)$/\1/p'`
-		if test "X${flag}" != X; then
-			PYTHON_LDFLAGS="$PYTHON_LDFLAGS ${flag}"
-		fi
-	done
-	# on some platforms, ${PYTHON}-config --ldflags doesn't provide a -L
-	# option while having the library under a non trivial directory.
-	# as a workaround we try the "lib" sub directory under the common
-	# prefix for this python.
-	if test -z "${PYTHON_LDFLAGS}"; then
-		PYTHON_LDFLAGS="-L`${PYTHON}-config --prefix`/lib"
-	fi
-else
-	if test "X$PYTHON_INCLUDES" = X -o "X$PYTHON_LDFLAGS" = X; then
-		AC_MSG_WARN([${PYTHON}-config does not exist or is not executable, so we could not detect python development environment.  Your system may require an additional package (e.g. "python3-dev").  Alternatively, if you are sure you have python headers and libraries, define PYTHON_INCLUDES and PYTHON_LDFLAGS and run this script.])
-	fi
-fi
-
-# Some OSes including NetBSD don't install libpython.so in a well known path.
-# To avoid requiring dynamic library path with our python wrapper loadable
-# modules, we embed the path to the modules when possible.  We do this even
-# when the path is known in the common operational environment (e.g. when
-# it's stored in a common "hint" file) for simplicity.
-if test "x$ISC_RPATH_FLAG" != "x"; then
-	python_rpath=
-	for flag in ${PYTHON_LDFLAGS}; do
-		python_rpath="${python_rpath} `echo $flag | ${SED} -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`"
-	done
-	PYTHON_LDFLAGS="${PYTHON_LDFLAGS} ${python_rpath}"
-fi
-
-AC_SUBST(PYTHON_INCLUDES)
-AC_SUBST(PYTHON_LDFLAGS)
-
-CPPFLAGS_SAVED="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS ${PYTHON_INCLUDES}"
-AC_CHECK_HEADERS([Python.h],, AC_MSG_ERROR([Missing Python.h]))
-CPPFLAGS="$CPPFLAGS_SAVED"
-
-# Check for python library.  Needed for Python-wrapper libraries.
-LDFLAGS_SAVED="$LDFLAGS"
-LDFLAGS="$LDFLAGS $PYTHON_LDFLAGS"
-python_bin="python${PYTHON_VERSION}"
-AC_CHECK_LIB($python_bin, main, python_lib=$python_bin, python_lib=no)
-if test $python_lib != "no"; then
-	PYTHON_LIB="-l$python_lib"
-fi
-AC_SUBST(PYTHON_LIB)
-LDFLAGS=$LDFLAGS_SAVED
-
-# Python 3.2 changed the return type of internal hash function to
-# Py_hash_t and some platforms (such as Solaris) strictly check for long
-# vs Py_hash_t. So we detect and use the appropriate return type.
-# Remove this test (and associated changes in pydnspp_config.h.in) when
-# we require Python 3.2.
-have_py_hash_t=0
-CPPFLAGS_SAVED="$CPPFLAGS"
-CPPFLAGS=${PYTHON_INCLUDES}
-AC_MSG_CHECKING(for Py_hash_t)
-AC_TRY_COMPILE([#include <Python.h>
-                Py_hash_t h;],,
-    [AC_MSG_RESULT(yes)
-     have_py_hash_t=1],
-    [AC_MSG_RESULT(no)])
-CPPFLAGS="$CPPFLAGS_SAVED"
-HAVE_PY_HASH_T=$have_py_hash_t
-AC_SUBST(HAVE_PY_HASH_T)
-
-# (g++ only check)
-# Python 3.2 has an unused parameter in one of its headers. This
-# has been reported, but not fixed as of yet, so we check if we need
-# to set -Wno-unused-parameter.
-if test "X$GXX" = "Xyes" -a "$werror_ok" = 1; then
-	CPPFLAGS_SAVED="$CPPFLAGS"
-	CPPFLAGS=${PYTHON_INCLUDES}
-	CXXFLAGS_SAVED="$CXXFLAGS"
-	CXXFLAGS="$CXXFLAGS $B10_CXXFLAGS -Werror"
-	AC_MSG_CHECKING([whether we need -Wno-unused-parameter for python])
-	AC_TRY_COMPILE(
-		[#include <Python.h>],
-		[],
-		[AC_MSG_RESULT(no)],
-		[
-		CXXFLAGS="$CXXFLAGS -Wno-unused-parameter"
-		AC_TRY_COMPILE([#include <Python.h>],
-		[],
-		[AC_MSG_RESULT(yes)
-		 PYTHON_CXXFLAGS="${PYTHON_CXXFLAGS} -Wno-unused-parameter"
-		 AC_SUBST(PYTHON_CXXFLAGS)
-		],
-		[AC_MSG_ERROR([Can't compile against Python.h.  If you're using MacOS X and have installed Python with Homebrew, see http://kea.isc.org/wiki/SystemNotesMacOSX])]
-                )
-                ]
-	)
-	CXXFLAGS="$CXXFLAGS_SAVED"
-	CPPFLAGS="$CPPFLAGS_SAVED"
-fi
-
 # produce PIC unless we disable shared libraries. need this for python bindings.
 if test $enable_shared != "no" -a "X$GXX" = "Xyes"; then
    B10_CXXFLAGS="$B10_CXXFLAGS -fPIC"
@@ -528,29 +393,6 @@ AC_TRY_COMPILE([
         AC_DEFINE(HAVE_SA_LEN, 1, [Define to 1 if sockaddr has a sa_len member, and corresponding sin_len and sun_len])],
         AC_MSG_RESULT(no))
 
-AC_ARG_WITH(pycoverage,
-[  --with-pycoverage[=PROGRAM]         enable python code coverage using the specified coverage], pycoverage="$withval", pycoverage="no")
-if test "$pycoverage" = "no" ; then
-	# just run the tests normally with python
-	PYCOVERAGE_RUN="${PYTHON}"
-	USE_PYCOVERAGE="no"
-elif test "$pycoverage" = "yes" ; then
-	PYCOVERAGE="coverage"
-	PYCOVERAGE_RUN="${PYCOVERAGE} run --branch --append"
-	USE_PYCOVERAGE="yes"
-else
-	PYCOVERAGE="$pycoverage"
-	PYCOVERAGE_RUN="${PYCOVERAGE} run --branch --append"
-	USE_PYCOVERAGE="yes"
-fi
-AM_CONDITIONAL(ENABLE_PYTHON_COVERAGE, test x$USE_PYCOVERAGE != xno)
-AC_SUBST(PYCOVERAGE)
-AC_SUBST(PYCOVERAGE_RUN)
-AC_SUBST(USE_PYCOVERAGE)
-
-
-
-
 enable_gtest="no"
 GTEST_INCLUDES=
 
@@ -1463,11 +1305,8 @@ AC_CONFIG_FILES([compatcheck/Makefile
                  src/lib/testutils/testdata/Makefile
                  src/lib/util/io/Makefile
                  src/lib/util/Makefile
-                 src/lib/util/python/doxygen2pydoc.py
                  src/lib/util/python/gen_wiredata.py
                  src/lib/util/python/Makefile
-                 src/lib/util/python/mkpywrapper.py
-                 src/lib/util/pyunittests/Makefile
                  src/lib/util/tests/Makefile
                  src/lib/util/threads/Makefile
                  src/lib/util/threads/tests/Makefile
@@ -1488,7 +1327,6 @@ AC_CONFIG_FILES([compatcheck/Makefile
            chmod +x src/lib/log/tests/local_file_test.sh
            chmod +x src/lib/log/tests/logger_lock_test.sh
            chmod +x src/lib/log/tests/severity_test.sh
-           chmod +x src/lib/python/isc/log/tests/log_console.py
            chmod +x src/lib/util/python/doxygen2pydoc.py
            chmod +x src/lib/util/python/gen_wiredata.py
            chmod +x src/lib/util/python/mkpywrapper.py

+ 1 - 1
src/bin/dhcp6/tests/Makefile.am

@@ -6,7 +6,7 @@ SHTESTS += dhcp6_reconfigure_test.sh
 SHTESTS += dhcp6_sigterm_test.sh
 SHTESTS += dhcp6_sigint_test.sh
 endif
-EXTRA_DIST = $(SHTESTS)
+EXTRA_DIST = $(SHTESTS) dhcp6_shutdown_test.sh
 
 # Explicitly specify paths to dynamic libraries required by loadable python
 # modules. That is required on Mac OS systems. Otherwise we will get exception

+ 77 - 0
src/lib/dns/tests/testdata/Makefile.am

@@ -118,5 +118,82 @@ EXTRA_DIST += broken.zone
 EXTRA_DIST += origincheck.txt
 EXTRA_DIST += omitcheck.txt
 
+# Generated .wire files
+EXTRA_DIST += edns_toWire1.wire edns_toWire2.wire
+EXTRA_DIST += edns_toWire3.wire edns_toWire4.wire
+EXTRA_DIST += message_fromWire10.wire
+EXTRA_DIST += message_fromWire11.wire message_fromWire12.wire
+EXTRA_DIST += message_fromWire13.wire message_fromWire14.wire
+EXTRA_DIST += message_fromWire15.wire message_fromWire16.wire
+EXTRA_DIST += message_fromWire17.wire message_fromWire18.wire
+EXTRA_DIST += message_fromWire19.wire message_fromWire20.wire
+EXTRA_DIST += message_fromWire21.wire message_fromWire22.wire
+EXTRA_DIST += message_toWire1 message_toWire2.wire message_toWire3.wire
+EXTRA_DIST += message_toWire4.wire message_toWire5.wire
+EXTRA_DIST += message_toText1.txt message_toText1.wire
+EXTRA_DIST += message_toText2.txt message_toText2.wire
+EXTRA_DIST += message_toText3.txt message_toText3.wire
+EXTRA_DIST += name_toWire5.wire name_toWire6.wire
+EXTRA_DIST += rdatafields1.wire rdatafields2.wire rdatafields3.wire
+EXTRA_DIST += rdatafields4.wire rdatafields5.wire rdatafields6.wire
+EXTRA_DIST += rdata_dnskey_fromWire.wire rdata_dnskey_empty_keydata_fromWire.wire
+EXTRA_DIST += rdata_nsec_fromWire4.wire rdata_nsec_fromWire5.wire
+EXTRA_DIST += rdata_nsec_fromWire6.wire rdata_nsec_fromWire7.wire
+EXTRA_DIST += rdata_nsec_fromWire8.wire rdata_nsec_fromWire9.wire
+EXTRA_DIST += rdata_nsec_fromWire10.wire
+EXTRA_DIST += rdata_nsec_fromWire16.wire
+EXTRA_DIST += rdata_nsec3param_fromWire2.wire
+EXTRA_DIST += rdata_nsec3param_fromWire11.wire
+EXTRA_DIST += rdata_nsec3param_fromWire13.wire
+EXTRA_DIST += rdata_nsec3_fromWire2.wire rdata_nsec3_fromWire3
+EXTRA_DIST += rdata_nsec3_fromWire4.wire rdata_nsec3_fromWire5.wire
+EXTRA_DIST += rdata_nsec3_fromWire6.wire rdata_nsec3_fromWire7.wire
+EXTRA_DIST += rdata_nsec3_fromWire8.wire rdata_nsec3_fromWire9.wire
+EXTRA_DIST += rdata_nsec3_fromWire10.wire rdata_nsec3_fromWire11.wire
+EXTRA_DIST += rdata_nsec3_fromWire12.wire rdata_nsec3_fromWire13.wire
+EXTRA_DIST += rdata_nsec3_fromWire14.wire rdata_nsec3_fromWire15.wire
+EXTRA_DIST += rdata_nsec3_fromWire16.wire rdata_nsec3_fromWire17.wire
+EXTRA_DIST += rdata_rrsig_fromWire2.wire
+EXTRA_DIST += rdata_rp_fromWire1.wire rdata_rp_fromWire2.wire
+EXTRA_DIST += rdata_rp_fromWire3.wire rdata_rp_fromWire4.wire
+EXTRA_DIST += rdata_rp_fromWire5.wire rdata_rp_fromWire6.wire
+EXTRA_DIST += rdata_rp_toWire1.wire rdata_rp_toWire2.wire
+EXTRA_DIST += rdata_sshfp_fromWire1.wire rdata_sshfp_fromWire2.wire
+EXTRA_DIST += rdata_sshfp_fromWire3.wire rdata_sshfp_fromWire4.wire
+EXTRA_DIST += rdata_sshfp_fromWire5.wire rdata_sshfp_fromWire6.wire
+EXTRA_DIST += rdata_sshfp_fromWire7.wire rdata_sshfp_fromWire8.wire
+EXTRA_DIST += rdata_afsdb_fromWire1.wire rdata_afsdb_fromWire2.wire
+EXTRA_DIST += rdata_afsdb_fromWire3.wire rdata_afsdb_fromWire4.wire
+EXTRA_DIST += rdata_afsdb_fromWire5.wire
+EXTRA_DIST += rdata_afsdb_toWire1.wire rdata_afsdb_toWire2.wire
+EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.wire
+EXTRA_DIST += rdata_minfo_fromWire1.wire rdata_minfo_fromWire2.wire
+EXTRA_DIST += rdata_minfo_fromWire3.wire rdata_minfo_fromWire4.wire
+EXTRA_DIST += rdata_minfo_fromWire5.wire rdata_minfo_fromWire6.wire
+EXTRA_DIST += rdata_minfo_toWire1.wire rdata_minfo_toWire2.wire
+EXTRA_DIST += rdata_minfo_toWireUncompressed1.wire
+EXTRA_DIST += rdata_minfo_toWireUncompressed2.wire
+EXTRA_DIST += rdata_txt_fromWire1 rdata_txt_fromWire2.wire
+EXTRA_DIST += rdata_txt_fromWire3.wire rdata_txt_fromWire4.wire
+EXTRA_DIST += rdata_txt_fromWire5.wire rdata_unknown_fromWire
+EXTRA_DIST += rdata_tlsa_fromWire3.wire rdata_tlsa_fromWire4.wire
+EXTRA_DIST += rdata_tlsa_fromWire5.wire rdata_tlsa_fromWire6.wire
+EXTRA_DIST += rdata_tlsa_fromWire7.wire rdata_tlsa_fromWire8.wire
+EXTRA_DIST += rdata_tsig_fromWire1.wire rdata_tsig_fromWire2.wire
+EXTRA_DIST += rdata_tsig_fromWire3.wire rdata_tsig_fromWire4.wire
+EXTRA_DIST += rdata_tsig_fromWire5.wire rdata_tsig_fromWire6.wire
+EXTRA_DIST += rdata_tsig_fromWire7.wire rdata_tsig_fromWire8.wire
+EXTRA_DIST += rdata_tsig_fromWire9.wire
+EXTRA_DIST += rdata_tsig_toWire1.wire rdata_tsig_toWire2.wire
+EXTRA_DIST += rdata_tsig_toWire3.wire rdata_tsig_toWire4.wire
+EXTRA_DIST += rdata_tsig_toWire5.wire
+EXTRA_DIST += rdata_caa_fromWire1.wire rdata_caa_fromWire2.wire
+EXTRA_DIST += rdata_caa_fromWire3.wire rdata_caa_fromWire4.wire
+EXTRA_DIST += tsigrecord_toWire1.wire tsigrecord_toWire2.wire
+EXTRA_DIST += tsig_verify1.wire tsig_verify2.wire tsig_verify3.wire
+EXTRA_DIST += tsig_verify4.wire tsig_verify5.wire tsig_verify6.wire
+EXTRA_DIST += tsig_verify7.wire tsig_verify8.wire tsig_verify9.wire
+EXTRA_DIST += tsig_verify10.wire
+
 .spec.wire:
 	$(PYTHON) $(top_builddir)/src/lib/util/python/gen_wiredata.py -o $@ $<

+ 1 - 2
src/lib/util/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = . io unittests tests pyunittests python threads
+SUBDIRS = . io unittests tests python threads
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
@@ -41,7 +41,6 @@ libkea_util_la_SOURCES += encode/binary_from_base16.h
 libkea_util_la_SOURCES += random/qid_gen.h random/qid_gen.cc
 libkea_util_la_SOURCES += random/random_number_generator.h
 
-EXTRA_DIST = python/pycppwrapper_util.h
 libkea_util_la_LIBADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 CLEANFILES = *.gcno *.gcda
 

+ 0 - 11
src/lib/util/io/Makefile.am

@@ -10,14 +10,3 @@ libkea_util_io_la_SOURCES += pktinfo_utilities.h
 libkea_util_io_la_LIBADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 
 CLEANFILES = *.gcno *.gcda
-
-pyexec_LTLIBRARIES = libutil_io_python.la
-# Python prefers .so, while some OSes (specifically MacOS) use a different
-# suffix for dynamic objects.  -module is necessary to work this around.
-libutil_io_python_la_LDFLAGS = -module -avoid-version
-libutil_io_python_la_SOURCES = fdshare_python.cc
-libutil_io_python_la_LIBADD = libkea-util-io.la
-libutil_io_python_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
-# Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be
-# placed after -Wextra defined in AM_CXXFLAGS
-libutil_io_python_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)

+ 0 - 98
src/lib/util/io/fdshare_python.cc

@@ -1,98 +0,0 @@
-// Copyright (C) 2010  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 "fd_share.h"
-
-
-static PyObject*
-fdshare_recv_fd(PyObject*, PyObject* args) {
-    int sock, fd;
-    if (!PyArg_ParseTuple(args, "i", &sock)) {
-        return (NULL);
-    }
-    fd = isc::util::io::recv_fd(sock);
-    return (Py_BuildValue("i", fd));
-}
-
-static PyObject*
-fdshare_send_fd(PyObject*, PyObject* args) {
-    int sock, fd, result;
-    if (!PyArg_ParseTuple(args, "ii", &sock, &fd)) {
-        return (NULL);
-    }
-    result = isc::util::io::send_fd(sock, fd);
-    return (Py_BuildValue("i", result));
-}
-
-static PyMethodDef fdshare_Methods[] = {
-    {"send_fd",  fdshare_send_fd, METH_VARARGS, ""},
-    {"recv_fd",  fdshare_recv_fd, METH_VARARGS, ""},
-    {NULL, NULL, 0, NULL}        /* Sentinel */
-};
-
-
-static PyModuleDef bind10_fdshare_python = {
-    { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
-    "bind10_fdshare",
-    "Python bindings for fdshare",
-    -1,
-    fdshare_Methods,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-
-PyMODINIT_FUNC
-PyInit_libutil_io_python(void) {
-    PyObject *mod = PyModule_Create(&bind10_fdshare_python);
-    if (mod == NULL) {
-        return (NULL);
-    }
-
-    PyObject* FD_SYSTEM_ERROR = Py_BuildValue("i",
-                                              isc::util::io::FD_SYSTEM_ERROR);
-    if (FD_SYSTEM_ERROR == NULL) {
-        Py_XDECREF(mod);
-        return (NULL);
-    }
-    int ret = PyModule_AddObject(mod, "FD_SYSTEM_ERROR", FD_SYSTEM_ERROR);
-    if (ret == -1) {
-        Py_XDECREF(FD_SYSTEM_ERROR);
-        Py_XDECREF(mod);
-        return (NULL);
-    }
-
-    PyObject* FD_OTHER_ERROR = Py_BuildValue("i",
-                                             isc::util::io::FD_OTHER_ERROR);
-    if (FD_OTHER_ERROR == NULL) {
-        Py_XDECREF(mod);
-        return (NULL);
-    }
-    ret = PyModule_AddObject(mod, "FD_OTHER_ERROR", FD_OTHER_ERROR);
-    if (-1 == ret) {
-        Py_XDECREF(FD_OTHER_ERROR);
-        Py_XDECREF(mod);
-        return (NULL);
-    }
-
-    return (mod);
-}
-

+ 0 - 3
src/lib/util/python/.gitignore

@@ -1,3 +0,0 @@
-/doxygen2pydoc.py
-/gen_wiredata.py
-/mkpywrapper.py

+ 2 - 3
src/lib/util/python/Makefile.am

@@ -1,3 +1,2 @@
-noinst_SCRIPTS = doxygen2pydoc.py gen_wiredata.py mkpywrapper.py const2hdr.py \
-	pythonize_constants.py
-EXTRA_DIST = const2hdr.py pythonize_constants.py
+noinst_SCRIPTS = const2hdr.py gen_wiredata.py
+EXTRA_DIST = const2hdr.py

+ 0 - 680
src/lib/util/python/doxygen2pydoc.py.in

@@ -1,680 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-r"""
-A helper to semi-auto generate Python docstring text from C++ Doxygen
-documentation.
-
-This script converts an XML-format doxygen documentation for C++ library
-into a template Python docstring for the corresponding Python version
-of the library.  While it's not perfect and you'll still need to edit the
-output by hand, but past experiments showed the script produces a pretty
-good template.  It will help provide more compatible documentation for
-both C++ and Python versions of library from a unified source (C++ Doxygen
-documentation) with minimizing error-prone and boring manual conversion.
-
-HOW TO USE IT
-
-1. Generate XML output by doxygen.  Use bind10/doc/Doxyfile-xml:
-
-  % cd bind10/doc
-  % doxygen Doxyfile-xml
-  (XML files will be generated under bind10/doc/html/xml)
-
-2. Identify the xml file of the conversion target (C++ class, function, etc)
-
-  This is a bit tricky.  You'll probably need to do manual search.
-  For example, to identify the xml file for a C++ class
-  isc::datasrc::memory::ZoneWriter, you might do:
-
-  % cd bind10/doc/html/xml
-  % grep ZoneWriter *.xml | grep 'kind="class"'
-  index.xml:  <compound refid="d4/d3c/classisc_1_1datasrc_1_1memory_1_1ZoneWriter" kind="class"><name>isc::datasrc::memory::ZoneWriter</name>
-
-  In this case the file under the d4/d3c directory (with .xml suffix) would
-  be the file you're looking for.
-
-3. Run this script for the xml file:
-
-  % python3 doxygen2pydoc.py <top_srcdir>/doc/html/xml/d4/d3c/classisc_1_1datasrc_1_1memory_1_1ZoneWriter.xml > output.cc
-
-  The template content is dumped to standard out (redirected to file
-  "output.cc" in this example).
-
-  Sometimes the script produces additional output to standard error,
-  like this:
-
-    Replaced camelCased terms:
-    resetMemorySegment => reset_memory_segment
-    getConfiguration => get_configuration
-
-  In BIND 10 naming convention for methods is different for C++ and
-  Python.  This script uses some heuristic guess to convert the
-  C++-style method names to likely Python-style ones, and the converted
-  method names are used in the dumped template.  In many cases the guessed
-  names are correct, but you should check this list and make adjustments
-  by hand if necessary.
-
-  If there's no standard error output, this type of conversion didn't
-  happen.
-
-4. Edit and copy the template
-
-  The dumped template has the following organization:
-
-    namespace {
-    #ifdef COPY_THIS_TO_MAIN_CC
-        { "cleanup", ZoneWriter_cleanup, METH_NOARGS,
-          ZoneWriter_cleanup_doc },
-        { "install", ZoneWriter_install, METH_NOARGS,
-          ZoneWriter_install_doc },
-        { "load", ZoneWriter_load, METH_VARARGS,
-          ZoneWriter_load_doc },
-    #endif // COPY_THIS_TO_MAIN_CC
-
-    const char* const ZoneWriter_doc = "\
-      ...
-    ";
-
-    const char* const ZoneWriter_install_doc = "\
-      ...
-    ";
-
-    ...
-    }
-
-  The ifdef-ed block is a template for class methods information
-  to be added to the corresponding PyMethodDef structure array
-  (your wrapper C++ source would have something like ZoneWriter_methods
-  of this type).  These lines should be copied there.  As long as
-  the method names and corresponding wrapper function (such as
-  ZoneWriter_cleanup) are correct you shouldn't have to edit this part
-  (and they would be normally correct, unless the guessed method name
-  conversion was needed).
-
-  The rest of the content is a sequence of constant C-string variables.
-  Usually the first variable corresponds to the class description, and
-  the rest are method descriptions (note that ZoneWriter_install_doc
-  is referenced from the ifdef-ed block).  The content of this part
-  would generally make sense, but you'll often need to make some
-  adjsutments by hand.  A common examples of such adjustment is to
-  replace "NULL" with "None".  Also, it's not uncommon that some part
-  of the description simply doesn't apply to the Python version or
-  that Python specific notes are needed.  So go through the description
-  carefully and make necessary changes.  A common practice is to add
-  comments for a summary of adjustments like this:
-
-    // Modifications:
-    // NULL->None
-    //  - removed notes about derived classes (which doesn't apply for python)
-    const char* const ZoneWriter_doc = "\
-      ...
-    ";
-  This note will help next time you need to auto-generate and edit the
-  template (probably because the original C++ document is updated).
-
-  You can simply copy this part to the main C++ wrapper file, but since
-  it's relatively large a common practice is to maintain it in a separate
-  file that is exclusively included from the main file: if the name of
-  the main file is zonewriter_python.cc, the pydoc strings would be copied
-  in zonewriter_python_inc.cc, and the main file would have this line:
-
-      #include "zonewriter_inc.cc"
-
-  (In case you are C++ language police: it's okay to use the unnamed
-  name space for a file to be included because it's essentially a part
-  of the single .cc file, not expected to be included by others).
-
-  In either case, the ifdef-ed part should be removed.
-
-ADVANCED FEATURES
-
-You can use a special "xmlonly" doxygen command in C++ doxygent document
-in order to include Python code excerpt (while hiding it from the doxygen
-output for the C++ version).  This command will be converted to
-a special XML tag in the XML output.
-
-The block enclosed by \xmlonly and \endxmlonly should contain
-a verbatim XML tag named "pythonlisting", in which the python code should
-be placed.
-/// \code
-///    Name name("example.com");
-///    std::cout << name.toText() << std::endl;
-/// \endcode
-///
-/// \xmlonly <pythonlisting>
-///    name = Name("example.com")
-///    print(name.to_text())
-/// </pythonlisting> \endxmlonly
-
-Note that there must be a blank line between \endcode and \xmlonly.
-doxygen2pydoc assume the pythonlisting tag is in a separate <para> node.
-This blank ensures doxygen will produce the XML file that meets the
-assumption.
-
-INTERNAL MEMO (incomplete, and not very unredable yet)
-
-This simplified utility assumes the following structure:
-...
-  <compounddef ...>
-    <compoundname>isc::dns::TSIGError</compoundname>
-    <sectiondef kind="user-defined">
-      constructor, destructor
-    </sectiondef>
-    <sectiondef kind="public-type">
-      ..
-    </sectiondef>
-    <sectiondef kind="public-func">
-      <memberdef kind="function"...>
-        <type>return type (if any)</type>
-        <argsstring>(...) [const]</argsstring>
-        <name>method name</name>
-        <briefdescription>method's brief description</briefdescription>
-        <detaileddescription>
-          <para>...</para>...
-          <para>
-            <parameterlist kind="exception">
-              <parameteritem>
-                <parameternamelist>
-                  <parametername>Exception name</parametername>
-                </parameternamelist>
-                <parameterdescription>
-                  <para>exception desc</para>
-                </parameterdescription>
-              </parameteritem>
-            </parameterlist>
-            <parameterlist kind="param">
-              <parameteritem>
-                <parameternamelist>
-                  <parametername>param name</parametername>
-                </parameternamelist>
-                <parameterdescription>
-                  <para>param desc</para>
-                </parameterdescription>
-              </parameteritem>
-              ...
-            </parameterlist>
-            <simplesect kind="return">Return value</simplesect>
-          </para>
-        </detaileddescription>
-      </memberdef>
-    </sectiondef>
-    <sectiondef kind="public-static-attrib|user-defined">
-      <memberdef kind="variable"...>
-        <name>class-specific-constant</name>
-        <initializer>value</initializer>
-        <brief|detaileddescription>paragraph(s)</brief|detaileddescription>
-    </sectiondef>
-    <briefdescription>
-      class's brief description
-    </briefdescription>
-    <detaileddescription>
-      class's detailed description
-    </detaileddescription>
-  </compounddef>
-"""
-
-import re, string, sys, textwrap
-from xml.dom.minidom import parse
-from textwrap import fill, dedent, TextWrapper
-
-camel_replacements = {}
-member_functions = []
-constructors = []
-class_variables = []
-
-RE_CAMELTERM = re.compile('([\s\.]|^)[a-z]+[A-Z]\S*')
-RE_SIMPLECAMEL = re.compile("([a-z])([A-Z])")
-RE_CAMELAFTERUPPER = re.compile("([A-Z])([A-Z])([a-z])")
-
-class Paragraph:
-    TEXT = 0
-    ITEMIZEDLIST = 1
-    CPPLISTING = 2
-    PYLISTING = 3
-    VERBATIM = 4
-
-    def __init__(self, xml_node):
-        if len(xml_node.getElementsByTagName("pythonlisting")) > 0:
-            self.type = self.PYLISTING
-            self.text = re.sub("///", "", get_text(xml_node))
-        elif len(xml_node.getElementsByTagName("verbatim")) > 0:
-            self.type = self.VERBATIM
-            self.text = get_text(xml_node)
-        elif len(xml_node.getElementsByTagName("programlisting")) > 0:
-            # We ignore node containing a "programlisting" tag.
-            # They are C++ example code, and we are not interested in them
-            # in pydoc.
-            self.type = self.CPPLISTING
-        elif len(xml_node.getElementsByTagName("itemizedlist")) > 0:
-            self.type = self.ITEMIZEDLIST
-            self.items = []
-            for item in xml_node.getElementsByTagName("listitem"):
-                self.items.append(get_text(item))
-        else:
-            self.type = self.TEXT
-
-            # A single textual paragraph could have multiple simple sections
-            # if it contains notes.
-
-            self.texts = []
-            subnodes = []
-            for child in xml_node.childNodes:
-                if child.nodeType == child.ELEMENT_NODE and \
-                        child.nodeName == 'simplesect' and \
-                        child.getAttribute('kind') == 'note':
-                    if len(subnodes) > 0:
-                        self.texts.append(get_text_fromnodelist(subnodes))
-                        subnodes = []
-                    subtext = 'Note: '
-                    for t in child.childNodes:
-                        subtext += get_text(t)
-                    self.texts.append(subtext)
-                else:
-                    subnodes.append(child)
-            if len(subnodes) > 0:
-                self.texts.append(get_text_fromnodelist(subnodes))
-
-    def dump(self, f, wrapper):
-        if self.type == self.CPPLISTING:
-            return
-        elif self.type == self.ITEMIZEDLIST:
-            for item in self.items:
-                item_wrapper = TextWrapper(\
-                    initial_indent=wrapper.initial_indent + "- ",
-                    subsequent_indent=wrapper.subsequent_indent + "  ")
-                dump_filled_text(f, item_wrapper, item)
-                f.write("\\n\\\n")
-        elif self.type == self.TEXT:
-            for text in self.texts:
-                if text != self.texts[0]:
-                    f.write("\\n\\\n")
-                dump_filled_text(f, wrapper, text)
-                f.write("\\n\\\n")
-        else:
-            dump_filled_text(f, None, self.text)
-            f.write("\\n\\\n")
-        f.write("\\n\\\n")
-
-class NamedItem:
-    def __init__(self, name, desc):
-        self.name = name
-        self.desc = desc
-
-    def dump(self, f, wrapper):
-        # we use deeper indent inside the item list.
-        new_initial_indent = wrapper.initial_indent + " " * 2
-        new_subsequent_indent = wrapper.subsequent_indent + " " * (2 + 11)
-        local_wrapper = TextWrapper(initial_indent=new_initial_indent,
-                                    subsequent_indent=new_subsequent_indent)
-
-        # concatenate name and description with a fixed width (up to 10 chars)
-        # for the name, and wrap the entire text, then dump it to file.
-        dump_filled_text(f, local_wrapper, "%-10s %s" % (self.name, self.desc))
-        f.write("\\n\\\n")
-
-class FunctionDefinition:
-    # function types
-    CONSTRUCTOR = 0
-    COPY_CONSTRUCTOR = 1
-    DESTRUCTOR = 2
-    ASSIGNMENT_OP = 3
-    OTHER = 4
-
-    def __init__(self):
-        self.type = self.OTHER
-        self.name = None
-        self.pyname = None
-        self.args = ""
-        self.ret_type = None
-        self.brief_desc = None
-        self.detailed_desc = []
-        self.exceptions = []
-        self.parameters = []
-        self.returns = None
-        self.have_param = False
-
-    def dump_doc(self, f, wrapper=TextWrapper()):
-        f.write(self.pyname + "(" + self.args + ")")
-        if self.ret_type is not None:
-            f.write(" -> " + self.ret_type)
-        f.write("\\n\\\n\\n\\\n")
-
-        if self.brief_desc is not None:
-            dump_filled_text(f, wrapper, self.brief_desc)
-            f.write("\\n\\\n\\n\\\n")
-
-        for para in self.detailed_desc:
-            para.dump(f, wrapper)
-
-        if len(self.exceptions) > 0:
-            f.write(wrapper.fill("Exceptions:") + "\\n\\\n")
-            for ex_desc in self.exceptions:
-                ex_desc.dump(f, wrapper)
-            f.write("\\n\\\n")
-        if len(self.parameters) > 0:
-            f.write(wrapper.fill("Parameters:") + "\\n\\\n")
-            for param_desc in self.parameters:
-                param_desc.dump(f, wrapper)
-            f.write("\\n\\\n")
-        if self.returns is not None:
-            dump_filled_text(f, wrapper, "Return Value(s): " + self.returns)
-            f.write("\\n\\\n")
-
-    def dump_pymethod_def(self, f, class_name):
-        f.write('    { "' + self.pyname + '", ')
-        f.write(class_name + '_' + self.name + ', ')
-        if len(self.parameters) == 0:
-            f.write('METH_NOARGS,\n')
-        else:
-            f.write('METH_VARARGS,\n')
-        f.write('      ' + class_name + '_' + self.name + '_doc },\n')
-
-class VariableDefinition:
-    def __init__(self, nodelist):
-        self.value = None
-        self.brief_desc = None
-        self.detailed_desc = []
-
-        for node in nodelist:
-            if node.nodeName == "name":
-                self.name = get_text(node)
-            elif node.nodeName == "initializer":
-                self.value = get_text(node)
-            elif node.nodeName == "briefdescription":
-                self.brief_desc = get_text(node)
-            elif node.nodeName == "detaileddescription":
-                for para in node.childNodes:
-                    if para.nodeName != "para":
-                        # ignore surrounding empty nodes
-                        continue
-                    self.detailed_desc.append(Paragraph(para))
-
-    def dump_doc(self, f, wrapper=TextWrapper()):
-        name_value = self.name
-        if self.value is not None:
-            name_value += ' = ' + self.value
-        dump_filled_text(f, wrapper, name_value)
-        f.write('\\n\\\n')
-
-        desc_initial_indent = wrapper.initial_indent + "  "
-        desc_subsequent_indent = wrapper.subsequent_indent + "  "
-        desc_wrapper = TextWrapper(initial_indent=desc_initial_indent,
-                                   subsequent_indent=desc_subsequent_indent)
-        if self.brief_desc is not None:
-            dump_filled_text(f, desc_wrapper, self.brief_desc)
-            f.write("\\n\\\n\\n\\\n")
-
-        for para in self.detailed_desc:
-            para.dump(f, desc_wrapper)
-
-def dump_filled_text(f, wrapper, text):
-    """Fill given text using wrapper, and dump it to the given file
-    appending an escaped CR at each end of line.
-    """
-    filled_text = wrapper.fill(text) if wrapper is not None else text
-    f.write("".join(re.sub("\n", r"\\n\\\n", filled_text)))
-
-def camel_to_lowerscores(matchobj):
-    oldtext = matchobj.group(0)
-    newtext = re.sub(RE_SIMPLECAMEL, r"\1_\2", oldtext)
-    newtext = re.sub(RE_CAMELAFTERUPPER, r"\1_\2\3", newtext)
-    newtext = newtext.lower()
-    camel_replacements[oldtext] = newtext
-    return newtext.lower()
-
-def cpp_to_python(text):
-    text = text.replace("::", ".")
-    text = text.replace('"', '\\"')
-
-    # convert camelCase to "_"-concatenated format
-    # (e.g. getLength -> get_length)
-    return re.sub(RE_CAMELTERM, camel_to_lowerscores, text)
-
-def convert_type_name(type_name):
-    """Convert C++ type name to python type name using common conventions"""
-    # strip off leading 'const' and trailing '&/*'
-    type_name = re.sub("^const\S*", "", type_name)
-    type_name = re.sub("\S*[&\*]$", "", type_name)
-
-    # We often typedef smart pointers as [Const]TypePtr.  Convert them to
-    # just "Type"
-    type_name = re.sub("^Const", "", type_name)
-    type_name = re.sub("Ptr$", "", type_name)
-
-    if type_name == "std::string":
-        return "string"
-    if re.search(r"(int\d+_t|size_t)", type_name):
-        return "integer"
-    return type_name
-
-def get_text(root, do_convert=True):
-    """Recursively extract bare text inside the specified node (root),
-    concatenate all extracted text and return the result.
-    """
-    nodelist = root.childNodes
-    rc = []
-    for node in nodelist:
-        if node.nodeType == node.TEXT_NODE:
-            if do_convert:
-                rc.append(cpp_to_python(node.data))
-            else:
-                rc.append(node.data)
-        elif node.nodeType == node.ELEMENT_NODE:
-            rc.append(get_text(node))
-    # return the result, removing any leading newlines (that often happens for
-    # brief descriptions, which will cause lines not well aligned)
-    return re.sub("^(\n*)", "", ''.join(rc))
-
-def get_text_fromnodelist(nodelist, do_convert=True):
-    """Recursively extract bare text inside the specified node (root),
-    concatenate all extracted text and return the result.
-    """
-    rc = []
-    for node in nodelist:
-        if node.nodeType == node.TEXT_NODE:
-            if do_convert:
-                rc.append(cpp_to_python(node.data))
-            else:
-                rc.append(node.data)
-        elif node.nodeType == node.ELEMENT_NODE:
-            rc.append(get_text(node))
-    # return the result, removing any leading newlines (that often happens for
-    # brief descriptions, which will cause lines not well aligned)
-    return re.sub("^(\n*)", "", ''.join(rc))
-
-def parse_parameters(nodelist):
-    rc = []
-    for node in nodelist:
-        if node.nodeName != "parameteritem":
-            continue
-        # for simplicity, we assume one parametername and one
-        # parameterdescription for each parameter.
-        name = get_text(node.getElementsByTagName("parametername")[0])
-        desc = get_text(node.getElementsByTagName("parameterdescription")[0])
-        rc.append(NamedItem(name, desc))
-    return rc
-
-def parse_function_description(func_def, nodelist):
-    for node in nodelist:
-        # nodelist contains beginning and ending empty text nodes.
-        # ignore them (otherwise they cause disruption below).
-        if node.nodeName != "para":
-            continue
-
-        if node.getElementsByTagName("parameterlist"):
-            # within this node there may be exception list, parameter list,
-            # and description for return value.  parse and store them
-            # seprately.
-            for paramlist in node.getElementsByTagName("parameterlist"):
-                if paramlist.getAttribute("kind") == "exception":
-                    func_def.exceptions = \
-                        parse_parameters(paramlist.childNodes)
-                elif paramlist.getAttribute("kind") == "param":
-                    func_def.parameters = \
-                        parse_parameters(paramlist.childNodes)
-            if node.getElementsByTagName("simplesect"):
-                simplesect = node.getElementsByTagName("simplesect")[0]
-                if simplesect.getAttribute("kind") == "return":
-                    func_def.returns = get_text(simplesect)
-        else:
-            # for normal text, python listing and itemized list, append them
-            # to the list of paragraphs
-            func_def.detailed_desc.append(Paragraph(node))
-
-def parse_function(func_def, class_name, nodelist):
-    for node in nodelist:
-        if node.nodeName == "name":
-            func_def.name = get_text(node, False)
-            func_def.pyname = cpp_to_python(func_def.name)
-        elif node.nodeName == "argsstring":
-            # extract parameter names only, assuming they immediately follow
-            # their type name + space, and are immeidatelly followed by
-            # either "," or ")".  If it's a pointer or reference, */& is
-            # prepended to the parameter name without a space:
-            # e.g. (int var1, char *var2, Foo &var3)
-            args = get_text(node, False)
-            # extract parameter names, possibly with */&
-            func_def.args = ', '.join(re.findall(r"\s(\S+)[,)]", args))
-            # then remove any */& symbols
-            func_def.args = re.sub("[\*&]", "", func_def.args)
-        elif node.nodeName == "type" and node.hasChildNodes():
-            func_def.ret_type = convert_type_name(get_text(node, False))
-        elif node.nodeName == "param":
-            func_def.have_param = True
-        elif node.nodeName == "briefdescription":
-            func_def.brief_desc = get_text(node)
-        elif node.nodeName == "detaileddescription":
-            parse_function_description(func_def, node.childNodes)
-    # identify the type of function using the name and arg
-    if func_def.name == class_name and \
-            re.search("^\(const " + class_name + " &[^,]*$", args):
-        # This function is ClassName(const ClassName& param), which is
-        # the copy constructor.
-        func_def.type = func_def.COPY_CONSTRUCTOR
-    elif func_def.name == class_name:
-        # if it's not the copy ctor but the function name == class name,
-        # it's a constructor.
-        func_def.type = func_def.CONSTRUCTOR
-    elif func_def.name == "~" + class_name:
-        func_def.type = func_def.DESTRUCTOR
-    elif func_def.name == "operator=":
-        func_def.type = func_def.ASSIGNMENT_OP
-
-    # register the definition to the approriate list
-    if func_def.type == func_def.CONSTRUCTOR:
-        constructors.append(func_def)
-    elif func_def.type == func_def.OTHER:
-        member_functions.append(func_def)
-
-def parse_functions(class_name, nodelist):
-    for node in nodelist:
-        if node.nodeName == "memberdef" and \
-                node.getAttribute("kind") == "function":
-            func_def = FunctionDefinition()
-            parse_function(func_def, class_name, node.childNodes)
-
-def parse_class_variables(class_name, nodelist):
-    for node in nodelist:
-        if node.nodeName == "memberdef" and \
-                node.getAttribute("kind") == "variable":
-            class_variables.append(VariableDefinition(node.childNodes))
-
-def dump(f, class_name, class_brief_doc, class_detailed_doc):
-    f.write("namespace {\n")
-
-    f.write('#ifdef COPY_THIS_TO_MAIN_CC\n')
-    for func in member_functions:
-        func.dump_pymethod_def(f, class_name)
-    f.write('#endif // COPY_THIS_TO_MAIN_CC\n\n')
-
-    f.write("const char* const " + class_name + '_doc = "\\\n')
-    if class_brief_doc is not None:
-        f.write("".join(re.sub("\n", r"\\n\\\n", fill(class_brief_doc))))
-        f.write("\\n\\\n")
-        f.write("\\n\\\n")
-    if len(class_detailed_doc) > 0:
-        for para in class_detailed_doc:
-            para.dump(f, wrapper=TextWrapper())
-
-    # dump constructors
-    for func in constructors:
-        indent = " " * 4
-        func.dump_doc(f, wrapper=TextWrapper(initial_indent=indent,
-                                             subsequent_indent=indent))
-
-    # dump class variables
-    if len(class_variables) > 0:
-        f.write("Class constant data:\\n\\\n")
-        for var in class_variables:
-            var.dump_doc(f)
-
-    f.write("\";\n")
-
-    for func in member_functions:
-        f.write("\n")
-        f.write("const char* const " + class_name + "_" + func.name + \
-                    "_doc = \"\\\n");
-        func.dump_doc(f)
-        f.write("\";\n")
-
-    f.write("} // unnamed namespace") # close namespace
-
-if __name__ == '__main__':
-    dom = parse(sys.argv[1])
-    class_elements = dom.getElementsByTagName("compounddef")[0].childNodes
-    class_brief_doc = None
-    class_detailed_doc = []
-    for node in class_elements:
-        if node.nodeName == "compoundname":
-            # class name is the last portion of the period-separated fully
-            # qualified class name. (this should exist)
-            class_name = re.split("\.", get_text(node))[-1]
-        if node.nodeName == "briefdescription":
-            # we assume a brief description consists at most one para
-            class_brief_doc = get_text(node)
-        elif node.nodeName == "detaileddescription":
-            # a detaild description consists of one or more paragraphs
-            for para in node.childNodes:
-                if para.nodeName != "para": # ignore surrounding empty nodes
-                    continue
-                class_detailed_doc.append(Paragraph(para))
-        elif node.nodeName == "sectiondef" and \
-                node.getAttribute("kind") == "public-func":
-            parse_functions(class_name, node.childNodes)
-        elif node.nodeName == "sectiondef" and \
-                node.getAttribute("kind") == "public-static-attrib":
-            parse_class_variables(class_name, node.childNodes)
-        elif node.nodeName == "sectiondef" and \
-                node.getAttribute("kind") == "user-defined":
-            # there are two possiblities: functions and variables
-            for child in node.childNodes:
-                if child.nodeName != "memberdef":
-                    continue
-                if child.getAttribute("kind") == "function":
-                    parse_function(FunctionDefinition(), class_name,
-                                   child.childNodes)
-                elif child.getAttribute("kind") == "variable":
-                    class_variables.append(VariableDefinition(child.childNodes))
-
-    dump(sys.stdout, class_name, class_brief_doc, class_detailed_doc)
-
-    if len(camel_replacements) > 0:
-        sys.stderr.write("Replaced camelCased terms:\n")
-        for oldterm in camel_replacements.keys():
-            sys.stderr.write("%s => %s\n" % (oldterm,
-                                             camel_replacements[oldterm]))

+ 0 - 100
src/lib/util/python/mkpywrapper.py.in

@@ -1,100 +0,0 @@
-#!@PYTHON@
-
-# Copyright (C) 2011  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-"""This utility program generates a C++ header and implementation files
-that can be used as a template of C++ python binding for a C++ class.
-
-Usage: ./mkpywrapper.py ClassName
-(the script should be run on this directory)
-
-It will generate two files: classname_python.h and classname_python.cc,
-many of whose definitions are in the namespace isc::MODULE_NAME::python.
-By default MODULE_NAME will be 'dns' (because this tool is originally
-intended to be used for the C++ python binding of the DNS library), but
-can be changed via the -m command line option.
-
-The generated files contain code fragments that are commonly used in
-C++ python binding implementations.  It will define a class named
-s_ClassName which is a derived class of PyModule and can meet the
-requirement of the CPPPyObjectContainer template class (see
-pycppwrapper_util.h).  It also defines (and declares in the header file)
-"classname_type", which is of PyTypeObject and is intended to be used
-to define details of the python bindings for the ClassName class.
-
-In many cases the header file can be used as a startpoint of the
-binding development without modification.  But you may want to make
-ClassName::cppobj a constant variable (and you should if you can).
-Many definitions of classname_python.cc should also be able to be used
-just as defined, but some will need to be changed or removed.  In
-particular, you should at least adjust ClassName_init().  You'll
-probably also need to add more definitions to that file to provide
-complete features of the C++ class.
-"""
-
-import datetime, string, sys
-from optparse import OptionParser
-
-# Remember the current year to produce the copyright boilerplate
-YEAR = datetime.date.today().timetuple()[0]
-
-def dump_file(out_file, temp_file, class_name, module):
-    for line in temp_file.readlines():
-        line = line.replace("@YEAR@", str(YEAR))
-        line = line.replace("@CPPCLASS@_H", class_name.upper() + "_H")
-        line = line.replace("@CPPCLASS@", class_name)
-        line = line.replace("@cppclass@", class_name.lower())
-        line = line.replace("@MODULE@", module)
-        out_file.write(line)
-
-def dump_wrappers(class_name, output, module):
-    try:
-        if output == "-":
-            header_file = sys.stdout
-        else:
-            header_file = open(output + "_python.h", "w")
-        header_template_file = open("wrapper_template.h", "r")
-        if output == "-":
-            impl_file = sys.stdout
-        else:
-            impl_file = open(output + "_python.cc", "w")
-        impl_template_file = open("wrapper_template.cc", "r")
-    except:
-        sys.stderr.write('Failed to open C++ file(s)\n')
-        sys.exit(1)
-    dump_file(header_file, header_template_file, class_name, module)
-    dump_file(impl_file, impl_template_file, class_name, module)
-
-usage = '''usage: %prog [options] class_name'''
-
-if __name__ == "__main__":
-    parser = OptionParser(usage=usage)
-    parser.add_option('-o', '--output', action='store', dest='output',
-                      default=None, metavar='FILE',
-                      help='prefix of output file names [default: derived from the class name]')
-    parser.add_option('-m', '--module', action='store', dest='module',
-                      default='dns',
-                      help='C++ module name of the wrapper (for namespaces) [default: dns]')
-    (options, args) = parser.parse_args()
-
-    if len(args) == 0:
-        parser.error('input file is missing')
-
-    class_name = args[0]
-    if not options.output:
-        options.output = class_name.lower()
-
-    dump_wrappers(class_name, options.output, options.module)

+ 0 - 335
src/lib/util/python/pycppwrapper_util.h

@@ -1,335 +0,0 @@
-// 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 PYCPPWRAPPER_UTIL_H
-#define PYCPPWRAPPER_UTIL_H 1
-
-#include <Python.h>
-
-#include <exceptions/exceptions.h>
-
-/**
- * @file pycppwrapper_util.h
- * @short Shared definitions for python/C(++) API
- *
- * This utility defines a set of convenient wrappers for the python C API
- * to use it safely from our C++ bindings.  The python C API has many pitfalls
- * such as not-so-consistent reference count policies.  Also, many existing
- * examples are careless about error handling.  It's easy to find on the net
- * example (even of "production use") python extensions like this:
- *
- * \code
- *     new_exception = PyErr_NewException("mymodule.Exception", NULL, NULL);
- *     // new_exception can be NULL, in which case the call to
- *     // PyModule_AddObject will cause a surprising disruption.
- *     PyModule_AddObject(mymodule, "Exception", new_exception); \endcode
- *
- * When using the python C API with C++, we should also be careful about
- * exception safety.  The underlying C++ code (including standard C++ libraries
- * and memory allocation) can throw exceptions, in which case we need to
- * make sure any intermediate python objects are cleaned up (we also need to
- * catch the C++ exceptions inside the binding and convert them to python
- * errors, but that's a different subject).  This is not a trivial task
- * because the python objects are represented as bare C pointers (so there's
- * no destructor) and we need to address the exception safety along with python
- * reference counters (so we cannot naively apply standard smart pointers).
- *
- * This utility tries to help address these issues.
- *
- * Also, it's intentional that this is a header-only utility.  This way the
- * C++ loadable module won't depend on another C++ library (which is not
- * necessarily wrong, but would increase management cost such as link-time
- * troubles only for a small utility feature).
- */
-
-namespace isc {
-namespace util {
-namespace python {
-
-/// This is thrown inside this utility when it finds a NULL pointer is passed
-/// when it should not be NULL.
-class PyCPPWrapperException : public isc::Exception {
-public:
-    PyCPPWrapperException(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// This helper class is similar to the standard autoptr and manages PyObject
-/// using some kind of RAII techniques.  It is, however, customized for the
-/// python C API.
-///
-/// A PyObjectContainer object is constructed with a pointer to PyObject,
-/// which is often just created dynamically.  The caller will eventually
-/// attach the object to a different python object (often a module or class)
-/// via specific methods or directly return it to the python interpreter.
-///
-/// There are two cases in destructing the object: with or without decreasing
-/// a reference to the PyObject.  If the object is intended to be an argument
-/// to another python C library that increases the reference to the object for
-/// itself, we should normally release our own reference; otherwise the
-/// reference will leak and the object won't be garbage collected.  Also, when
-/// an unexpected error happens in the form of C++ exception, we should
-/// release the reference to prevent resource leak.
-///
-/// In some other cases, we should simply give our reference to the caller.
-/// That is the case when the created object itself is a return value of
-/// an extended python method written in the C++ binding.  Likewise, some
-/// python C library functions "steal" the reference.  In these cases we
-/// should not decrease the reference; otherwise it would cause duplicate free.
-///
-/// By default, the destructor of this class releases the reference to the
-/// PyObject.  If this behavior is desirable, you can extract the original
-/// bare pointer to the PyObject by the \c get() method.  If you don't want
-/// the reference to be decreased, the original bare pointer should be
-/// extracted using the \c release() method.
-///
-/// In some other cases, it would be convenient if it's possible to create
-/// an "empty" container and reset it with a Python object later.
-/// For example, we may want to create a temporary Python object in the
-/// middle of a function and make sure that it's valid within the rest of
-/// the function scope, while we want to make sure its reference is released
-/// when the function returns (either normally or as a result of exception).
-/// To allow this scenario, this class defines the default constructor
-/// and the \c reset() method.  The default constructor allows the class
-/// object with an "empty" (NULL) Python object, while \c reset() allows
-/// the stored object to be replaced with a new one.  If there's a valid
-/// object was already set, \c reset() releases its reference.
-/// In general, it's safer to construct the container object with a valid
-/// Python object pointer.  The use of the default constructor and
-/// \c reset() should therefore be restricted to cases where it's
-/// absolutely necessary.
-///
-/// There are two convenience methods for commonly used operations:
-/// \c installAsClassVariable() to add the PyObject as a class variable
-/// and \c installToModule to add the PyObject to a specified python module.
-/// These methods (at least to some extent) take care of the reference to
-/// the object (either release or keep) depending on the usage context so
-/// that the user don't have to worry about it.
-///
-/// On construction, this class expects the pointer can be NULL.
-/// If it happens it immediately throws a \c PyCPPWrapperException exception.
-/// This behavior is to convert failures in the python C API (such as
-/// PyObject_New() returning NULL) to C++ exception so that we can unify
-/// error handling in the style of C++ exceptions.
-///
-/// Examples 1: To create a tuple of two python objects, do this:
-///
-/// \code
-///     try {
-///         PyObjectContainer container0(Py_BuildValue("I", 0));
-///         PyObjectContainer container1(Py_BuildValue("s", cppobj.toText().c_str()));
-///         return (Py_BuildValue("OO", container0.get(), container1.get()));
-///     } catch { ... set python exception, etc ... } \endcode
-///
-/// Commonly deployed buggy implementation to achieve this would be like this:
-/// \code
-///    return (Py_BuildValue("OO", Py_BuildValue("I", 0),
-///                          Py_BuildValue("s", cppobj.toText().c_str())));
-/// \endcode
-/// One clear bug of this code is that references to the element objects of
-/// the tuple will leak.
-/// (Assuming \c cppobj.toText() can throw) this code is also not exception
-/// safe; if \c cppobj.toText() throws the reference to the first object
-/// will leak, even if the code tried to do the necessary cleanup in the
-/// successful case.
-/// Further, this code naively passes the result of the first two calls to
-/// \c Py_BuildValue() to the third one even if they can be NULL.
-/// In this specific case, it happens to be okay because \c Py_BuildValue()
-/// accepts NULL and treats it as an indication of error.  But not all
-/// python C library works that way (remember, the API is so inconsistent)
-/// and we need to refer to the API manual every time we have to worry about
-/// passing a NULL object to a library function.  We'd certainly like to
-/// avoid such development overhead.  The code using \c PyObjectContainer
-/// addresses all these problems.
-///
-/// Examples 2: Install a (constant) variable to a class.
-///
-/// \code
-///    try {
-///        // installClassVariable is a wrapper of
-///        // PyObjectContainer::installAsClassVariable.  See below.
-///        installClassVariable(myclass_type, "SOME_CONSTANT",
-///                             Py_BuildValue("I", 0));
-///    } catch { ... }
-/// \endcode
-///
-/// Examples 3: Install a custom exception to a module.
-///
-/// \code
-///    PyObject* new_exception; // publicly visible
-///    ...
-///    try {
-///        new_exception = PyErr_NewException("mymodule.NewException",
-///                                           NULL, NULL);
-///        PyObjectContainer(new_exception).installToModule(mymodule,
-///                                                         "NewException");
-///    } catch { ... }
-/// \endcode
-///
-/// Note that \c installToModule() keeps the reference to \c new_exception
-/// by default.  This is a common practice when we introduce a custom
-/// exception in a python biding written in C/C++.  See the code comment
-/// of the method for more details.
-struct PyObjectContainer {
-    PyObjectContainer() : obj_(NULL) {}
-    PyObjectContainer(PyObject* obj) : obj_(obj) {
-        if (obj_ == NULL) {
-            isc_throw(PyCPPWrapperException, "Unexpected NULL PyObject, "
-                      "probably due to short memory");
-        }
-    }
-    ~PyObjectContainer() {
-        if (obj_ != NULL) {
-            Py_DECREF(obj_);
-        }
-    }
-    void reset(PyObject* obj) {
-        if (obj == NULL) {
-            isc_throw(PyCPPWrapperException, "Unexpected NULL PyObject, "
-                      "probably due to short memory");
-        }
-        if (obj_ != NULL) {
-            Py_DECREF(obj_);
-        }
-        obj_ = obj;
-    }
-    PyObject* get() {
-        return (obj_);
-    }
-    PyObject* release() {
-        PyObject* ret = obj_;
-        obj_ = NULL;
-        return (ret);
-    }
-
-    // Install the enclosed PyObject to the specified python class 'pyclass'
-    // as a variable named 'name'.
-    void installAsClassVariable(PyTypeObject& pyclass, const char* name) {
-        if (PyDict_SetItemString(pyclass.tp_dict, name, obj_) < 0) {
-            isc_throw(PyCPPWrapperException, "Failed to set a class variable, "
-                      "probably due to short memory");
-        }
-        // Ownership successfully transferred to the class object.  We'll let
-        // it be released in the destructor.
-    }
-
-    // Install the enclosed PyObject to the specified module 'mod' as an
-    // object named 'name'.
-    // By default, this method explicitly keeps the reference to the object
-    // even after the module "steals" it.  To cancel this behavior and give
-    // the reference to the module completely, the third parameter 'keep_ref'
-    // should be set to false.
-    void installToModule(PyObject* mod, const char* name,
-                         bool keep_ref = true)
-    {
-        if (PyModule_AddObject(mod, name, obj_) < 0) {
-            isc_throw(PyCPPWrapperException, "Failed to add an object to "
-                      "module, probably due to short memory");
-        }
-        // PyModule_AddObject has "stolen" the reference, so unless we
-        // have to retain it ourselves we don't (shouldn't) decrease it.
-        // However, we actually often need to keep our own reference because
-        // objects added to a module are often referenced via non local
-        // C/C++ variables in various places of the C/C++ code.  In order
-        // for the code to run safely even if some buggy/evil python program
-        // performs 'del mod.obj', we need the extra reference.  See, e.g.:
-        // http://docs.python.org/py3k/c-api/init.html#Py_Initialize
-        // http://mail.python.org/pipermail/python-dev/2005-June/054238.html
-        if (keep_ref) {
-            Py_INCREF(obj_);
-        }
-        obj_ = NULL;
-    }
-
-protected:
-    PyObject* obj_;
-};
-
-/// This templated class is a derived class of \c PyObjectContainer and
-/// manages C++-class based python objects.
-///
-/// The template parameter \c PYSTRUCT must be a derived class (structure) of
-/// \c PyObject that has a member variable named \c cppobj, which must be a
-/// a pointer to \c CPPCLASS (the second template parameter).
-///
-/// For example, to define a custom python class based on a C++ class, MyClass,
-/// we'd define a class (struct) named \c s_MyClass like this:
-/// \code
-///    class s_MyClass : public PyObject {
-///    public:
-///       s_MyClass() : cppobj(NULL) {}
-///       MyClass* cppobj;
-///    };
-/// \endcode
-///
-/// And, to build and return a python version of MyClass object, write the
-/// following C++ code:
-/// \code
-///    typedef CPPPyObjectContainer<s_MyClass, MyClass> MyContainer;
-///    try {
-///        // below, myclass_type is of \c PyTypeObject that defines
-///        // a python class (type) for MyClass
-///        MyContainer container(PyObject_New(s_MyClass, myclass_type));
-///        container.set(new MyClass());
-///        return (container.release()); // give the reference to the caller
-///    } catch { ... }
-/// \endcode
-///
-/// This code prevents bugs like NULL pointer dereference when \c PyObject_New
-/// fails or resource leaks when new'ing \c MyClass results in an exception.
-/// Note that we use \c release() (derived from the base class) instead of
-/// \c get(); in this case we should simply pass the reference generated in
-/// \c PyObject_New() to the caller.
-template <typename PYSTRUCT, typename CPPCLASS>
-struct CPPPyObjectContainer : public PyObjectContainer {
-    explicit CPPPyObjectContainer(PYSTRUCT* obj) : PyObjectContainer(obj) {}
-
-    // This method associates a C++ object with the corresponding python
-    // object enclosed in this class.
-    void set(CPPCLASS* value) {
-        if (value == NULL) {
-            isc_throw(PyCPPWrapperException, "Unexpected NULL C++ object, "
-                      "probably due to short memory");
-        }
-        static_cast<PYSTRUCT*>(obj_)->cppobj = value;
-    }
-
-    // This is a convenience short cut to associate a C++ object with the
-    // python object and install it to the specified python class \c pyclass
-    // as a variable named \c name.
-    void installAsClassVariable(PyTypeObject& pyclass, const char* name,
-                                CPPCLASS* value)
-    {
-        set(value);
-        PyObjectContainer::installAsClassVariable(pyclass, name);
-    }
-};
-
-/// A shortcut function to install a python class variable.
-///
-/// It installs a python object \c obj to a specified class \c pyclass
-/// as a variable named \c name.
-inline void
-installClassVariable(PyTypeObject& pyclass, const char* name, PyObject* obj) {
-    PyObjectContainer(obj).installAsClassVariable(pyclass, name);
-}
-
-} // namespace python
-} // namespace util
-} // namespace isc
-#endif // PYCPPWRAPPER_UTIL_H
-
-// Local Variables:
-// mode: c++
-// End:

+ 0 - 57
src/lib/util/python/pythonize_constants.py

@@ -1,57 +0,0 @@
-# Copyright (C) 2013  Internet Systems Consortium.
-#
-# Permission to use, copy, modify, and 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-'''
-This script takes a C++ file with constants and converts it to a python
-module. However, the syntax it parses is very limited (it doesn't understand
-C++ at all, it just looks for lines containing the equal sign and strips
-what it thinks might be type).
-
-The purpose is to keep the same values of constants in C++ and python. This
-saves the work of keeping the constants in sync manually and is less error
-prone.
-'''
-
-import sys
-import re
-
-if len(sys.argv) != 3:
-    sys.stderr.write("Usage: python3 ./pythonize_constants.py input.cc output.py\n")
-    sys.exit(1)
-
-[filename_in, filename_out] = sys.argv[1:3]
-
-# Ignore preprocessor, namespaces and the ends of namespaces.
-ignore = re.compile('^(#|namespace|})')
-comment = re.compile('^//(.*)')
-constant = re.compile('^[a-zA-Z].*?([a-zA-Z_0-9]+\\s*=.*);')
-
-with open(filename_in) as file_in, open(filename_out, "w") as file_out:
-    file_out.write("# This file is generated from " + filename_in + "\n" +
-                   "# by the pythonize_constants.py script.\n" +
-                   "# Do not edit, all changes will be lost.\n\n")
-    for line in file_in:
-        if ignore.match(line):
-            continue
-        # Mangle comments to be python-like
-        line = comment.sub('#\\1', line)
-        # Extract the constant.
-
-        # TODO: We may want to do something with the true vs. True and
-        # NULL vs. None and such. Left out for now, since none are in
-        # the input file currently.
-        line = constant.sub('\\1', line)
-
-        file_out.write(line)

+ 0 - 291
src/lib/util/python/wrapper_template.cc

@@ -1,291 +0,0 @@
-// Copyright (C) @YEAR@  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 "@cppclass@_python.h"
-
-using namespace std;
-using namespace isc::util::python;
-using namespace isc::@MODULE@;
-using namespace isc::@MODULE@::python;
-
-//
-// @CPPCLASS@
-//
-
-// Trivial constructor.
-s_@CPPCLASS@::s_@CPPCLASS@() : cppobj(NULL) {
-}
-
-namespace {
-// Shortcut type which would be convenient for adding class variables safely.
-typedef CPPPyObjectContainer<s_@CPPCLASS@, @CPPCLASS@> @CPPCLASS@Container;
-
-@REMOVE_THIS_ON_RELEASE@
-// 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
-@CPPCLASS@_init(PyObject* po_self, PyObject* args, PyObject*) {
-    s_@CPPCLASS@* self = static_cast<s_@CPPCLASS@*>(po_self);
-    try {
-        if (PyArg_ParseTuple(args, "REPLACE ME")) {
-            @REMOVE_THIS_ON_RELEASE@
-            // YOU'LL NEED SOME VALIDATION, PREPARATION, ETC, HERE.
-            self->cppobj = new @CPPCLASS@(/*NECESSARY PARAMS*/);
-            return (0);
-        }
-    } catch (const exception& ex) {
-        const string ex_what = "Failed to construct @CPPCLASS@ object: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-        return (-1);
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError, "Unexpected C++ exception");
-        return (-1);
-    }
-
-    @REMOVE_THIS_ON_RELEASE@
-    // If we are here PyArg_ParseTuple() failed and TypeError should have
-    // been set.  If the constructor is more complicated and the control
-    // could reach this point for other reasons, an appropriate Python
-    // exception should be set by PyErr_SetString.
-
-    return (-1);
-}
-
-@REMOVE_THIS_ON_RELEASE@
-// 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
-@CPPCLASS@_destroy(PyObject* po_self) {
-    s_@CPPCLASS@* self = static_cast<s_@CPPCLASS@*>(po_self);
-    delete self->cppobj;
-    self->cppobj = NULL;
-    Py_TYPE(self)->tp_free(self);
-}
-
-@REMOVE_THIS_ON_RELEASE@
-// This should be able to be used without modification as long as the
-// underlying C++ class has toText().
-PyObject*
-@CPPCLASS@_toText(PyObject* po_self) {
-    const s_@CPPCLASS@* self = static_cast<const s_@CPPCLASS@*>(po_self);
-    try {
-        // toText() could throw, so we need to catch any exceptions below.
-        return (Py_BuildValue("s", self->cppobj->toText().c_str()));
-    } catch (const exception& ex) {
-        const string ex_what =
-            "Failed to convert @CPPCLASS@ object to text: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
-                        "converting @CPPCLASS@ object to text");
-    }
-    return (NULL);
-}
-
-PyObject*
-@CPPCLASS@_str(PyObject* self) {
-    // Simply call the to_text method we already defined
-    return (PyObject_CallMethod(self, const_cast<char*>("to_text"),
-                                const_cast<char*>("")));
-}
-
-@REMOVE_THIS_ON_RELEASE@
-// This is quite specific isc.dns.  For other wrappers this should probably
-// be removed.
-PyObject* @CPPCLASS@_toWire(PyObject* self, PyObject* args) {
-}
-
-PyObject* 
-@CPPCLASS@_richcmp(PyObject* po_self, PyObject* po_other, const int op) {
-    const s_@CPPCLASS@* const self = static_cast<const s_@CPPCLASS@*>(po_self);
-    const s_@CPPCLASS@* const other =
-        static_cast<const s_@CPPCLASS@*>(po_other);
-
-    bool c = false;
-
-    // Check for null and if the types match. If different type,
-    // simply return False
-    if (other == NULL || (self->ob_type != other->ob_type)) {
-        Py_RETURN_FALSE;
-    }
-
-    // Only equals and not equals here, unorderable type
-    switch (op) {
-    case Py_LT:
-        PyErr_SetString(PyExc_TypeError, "Unorderable type; @CPPCLASS@");
-        return (NULL);
-    case Py_LE:
-        PyErr_SetString(PyExc_TypeError, "Unorderable type; @CPPCLASS@");
-        return (NULL);
-    case Py_EQ:
-        c = (*self->cppobj == *other->cppobj);
-        break;
-    case Py_NE:
-        c = (*self->cppobj != *other->cppobj);
-        break;
-    case Py_GT:
-        PyErr_SetString(PyExc_TypeError, "Unorderable type; @CPPCLASS@");
-        return (NULL);
-    case Py_GE:
-        PyErr_SetString(PyExc_TypeError, "Unorderable type; @CPPCLASS@");
-        return (NULL);
-    }
-    if (c) {
-        Py_RETURN_TRUE;
-    } else {
-        Py_RETURN_FALSE;
-    }
-}
-
-// 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 @CPPCLASS@_methods[] = {
-    { "to_text", @CPPCLASS@_toText, METH_NOARGS,
-      @CPPCLASS@_toText_doc },
-
-    @REMOVE_THIS_ON_RELEASE@
-    // This is quite specific isc.dns.  For other wrappers this should probably
-    // be removed:
-    { "to_wire", @CPPCLASS@_toWire, METH_VARARGS,
-      @CPPCLASS@_toWire_doc },
-    { NULL, NULL, 0, NULL }
-};
-} // end of unnamed namespace
-
-namespace isc {
-namespace @MODULE@ {
-namespace python {
-// This defines the complete type for reflection in python and
-// parsing of PyObject* to s_@CPPCLASS@
-// Most of the functions are not actually implemented and NULL here.
-PyTypeObject @cppclass@_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "@MODULE@.@CPPCLASS@",
-    sizeof(s_@CPPCLASS@),                 // tp_basicsize
-    0,                                  // tp_itemsize
-    @CPPCLASS@_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
-    // THIS MAY HAVE TO BE CHANGED TO NULL:
-    @CPPCLASS@_str,                       // tp_str
-    NULL,                               // tp_getattro
-    NULL,                               // tp_setattro
-    NULL,                               // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    @CPPCLASS@_doc,
-    NULL,                               // tp_traverse
-    NULL,                               // tp_clear
-    // THIS MAY HAVE TO BE CHANGED TO NULL:
-    @CPPCLASS@_richcmp,                 // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    NULL,                               // tp_iter
-    NULL,                               // tp_iternext
-    @CPPCLASS@_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
-    @CPPCLASS@_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_@CPPCLASS@(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(&@cppclass@_type) < 0) {
-        return (false);
-    }
-    void* p = &@cppclass@_type;
-    if (PyModule_AddObject(mod, "@CPPCLASS@", static_cast<PyObject*>(p)) < 0) {
-        return (false);
-    }
-    Py_INCREF(&@cppclass@_type);
-
-    @REMOVE_THIS_ON_RELEASE@
-    // The following template is the typical procedure for installing class
-    // variables.  If the class doesn't have a class variable, remove the
-    // entire try-catch clauses.
-    try {
-        // Constant class variables
-        installClassVariable(@cppclass@_type, "REPLACE_ME",
-                             Py_BuildValue("REPLACE ME"));
-    } catch (const exception& ex) {
-        const string ex_what =
-            "Unexpected failure in @CPPCLASS@ initialization: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-        return (false);
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure in @CPPCLASS@ initialization");
-        return (false);
-    }
-
-    return (true);
-}
-
-PyObject*
-create@CPPCLASS@Object(const @CPPCLASS@& source) {
-    @CPPCLASS@Container container(PyObject_New(s_@CPPCLASS@,
-                                               &@cppclass@_type));
-    container.set(new @CPPCLASS@(source));
-    return (container.release());
-}
-} // namespace python
-} // namespace @MODULE@
-} // namespace isc

+ 0 - 59
src/lib/util/python/wrapper_template.h

@@ -1,59 +0,0 @@
-// Copyright (C) @YEAR@  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_@CPPCLASS@_H
-#define PYTHON_@CPPCLASS@_H 1
-
-#include <Python.h>
-
-namespace isc {
-namespace @MODULE@ {
-class @CPPCLASS@;
-
-namespace python {
-
-// The s_* Class simply covers one instantiation of the object
-class s_@CPPCLASS@ : public PyObject {
-public:
-    s_@CPPCLASS@();
-    @CPPCLASS@* cppobj;
-};
-
-extern PyTypeObject @cppclass@_type;
-
-bool initModulePart_@CPPCLASS@(PyObject* mod);
-
-// Note: this utility function works only when @CPPCLASS@ is a copy
-// constructable.
-// And, it would only be useful when python binding needs to create this
-// object frequently.  Otherwise, it would (or should) probably be better to
-// remove the declaration and definition of this function.
-//
-/// This is a simple shortcut to create a python @CPPCLASS@ object (in the
-/// form of a pointer to PyObject) with minimal exception safety.
-/// On success, it returns a valid pointer to PyObject with a reference
-/// counter of 1; if something goes wrong it throws an exception (it never
-/// returns a NULL pointer).
-/// This function is expected to be called within a try block
-/// followed by necessary setup for python exception.
-PyObject* create@CPPCLASS@Object(const @CPPCLASS@& source);
-
-} // namespace python
-} // namespace @MODULE@
-} // namespace isc
-#endif // PYTHON_@CPPCLASS@_H
-
-// Local Variables:
-// mode: c++
-// End:

+ 0 - 22
src/lib/util/pyunittests/Makefile.am

@@ -1,22 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CXXFLAGS = $(B10_CXXFLAGS)
-
-noinst_LTLIBRARIES = pyunittests_util.la
-
-pyunittests_util_la_SOURCES = pyunittests_util.cc
-pyunittests_util_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
-pyunittests_util_la_LDFLAGS = $(PYTHON_LDFLAGS)
-# Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be
-# placed after -Wextra defined in AM_CXXFLAGS
-pyunittests_util_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
-
-# Python prefers .so, while some OSes (specifically MacOS) use a different
-# suffix for dynamic objects.  -module is necessary to work this around.
-pyunittests_util_la_LDFLAGS += -module -avoid-version
-pyunittests_util_la_LIBADD = $(top_builddir)/src/lib/util/libkea-util.la
-pyunittests_util_la_LIBADD += $(PYTHON_LIB)
-
-# hack to trigger libtool to not create a convenience archive,
-# resulting in shared modules
-pyunittests_util_la_LDFLAGS += -rpath /nowhere

+ 0 - 84
src/lib/util/pyunittests/pyunittests_util.cc

@@ -1,84 +0,0 @@
-// 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.
-
-#include <Python.h>
-
-#include <stdint.h>
-
-// see util/time_utilities.h
-namespace isc {
-namespace util {
-namespace detail {
-extern int64_t (*gettimeFunction)();
-}
-}
-}
-
-namespace {
-int64_t fake_current_time;
-
-int64_t
-getFakeTime() {
-    return (fake_current_time);
-}
-
-PyObject*
-fixCurrentTime(PyObject*, PyObject* args) {
-    PyObject* maybe_none;
-    if (PyArg_ParseTuple(args, "L", &fake_current_time)) {
-        isc::util::detail::gettimeFunction = getFakeTime;
-    } else if (PyArg_ParseTuple(args, "O", &maybe_none) &&
-               maybe_none == Py_None) {
-        isc::util::detail::gettimeFunction = NULL;
-    } else {
-         PyErr_SetString(PyExc_TypeError, "Invalid arguments to "
-                         "pyunittests_util.fix_current_time");
-         return (NULL);
-    }
-
-    PyErr_Clear();
-    Py_RETURN_NONE;
-}
-
-PyMethodDef PyUnittestsUtilMethods[] = {
-    { "fix_current_time", fixCurrentTime, METH_VARARGS,
-      "Fix the current system time at the specified (fake) value.\n\n"
-      "This is useful for testing modules that depend on the current time.\n"
-      "Note that it only affects C++ modules that use gettimeWrapper() "
-      "defined in libutil, which allows a hook for testing.\n"
-      "If an integer (signed 64bit) is given, the current time will be fixed "
-      "to that value; if None is specified (which is the default) the use of "
-      "faked time will be canceled."
-    },
-    { NULL, NULL, 0, NULL}
-};
-
-PyModuleDef pyunittests_util = {
-    { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
-    "pyunittests_util",
-    "This module is a collection of utilities useful for testing "
-    "the BIND 10 C++ binding modules.",
-    -1,
-    PyUnittestsUtilMethods,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-} // end of unnamed namespace
-
-PyMODINIT_FUNC
-PyInit_pyunittests_util(void) {
-    return (PyModule_Create(&pyunittests_util));
-}