Browse Source

partial python wrapper implementation, see src/lib/dns/python/README for details

git-svn-id: svn://bind10.isc.org/svn/bind10/experiments/python-binding@1711 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen 15 years ago
parent
commit
460885237d

+ 3 - 0
configure.ac

@@ -373,6 +373,7 @@ AC_CONFIG_FILES([Makefile
                  src/lib/config/tests/Makefile
                  src/lib/dns/Makefile
                  src/lib/dns/tests/Makefile
+                 src/lib/dns/python/Makefile
                  src/lib/dns-python/Makefile
                  src/lib/exceptions/Makefile
                  src/lib/auth/Makefile
@@ -409,6 +410,7 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            src/lib/config/tests/data_def_unittests_config.h
            src/lib/python/isc/config/tests/config_test
            src/lib/python/isc/cc/tests/cc_test
+           src/lib/dns/python/tests/libdns_python_test
            src/lib/dns/gen-rdatacode.py
            src/lib/dns/tests/testdata/gen-wiredata.py
           ], [
@@ -427,5 +429,6 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            chmod +x src/bin/msgq/msgq_test
            chmod +x src/lib/dns/gen-rdatacode.py
            chmod +x src/lib/dns/tests/testdata/gen-wiredata.py
+           chmod +x src/lib/dns/python/tests/libdns_python_test
           ])
 AC_OUTPUT

+ 1 - 1
src/lib/dns/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = . tests
+SUBDIRS = . tests python
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 if GCC_WERROR_OK

+ 588 - 0
src/lib/dns/python/Makefile

@@ -0,0 +1,588 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# src/lib/dns/python/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+pkgdatadir = $(datadir)/bind10-devel
+pkgincludedir = $(includedir)/bind10-devel
+pkglibdir = $(libdir)/bind10-devel
+pkglibexecdir = $(libexecdir)/bind10-devel
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+subdir = src/lib/dns/python
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libdns_python_la_DEPENDENCIES = $(top_builddir)/src/lib/dns/libdns.la \
+	$(top_builddir)/src/lib/exceptions/libexceptions.la \
+	$(am__DEPENDENCIES_1)
+am_libdns_python_la_OBJECTS = libdns_python_la-libdns_python.lo \
+	libdns_python_la-libdns_python_common.lo
+libdns_python_la_OBJECTS = $(am_libdns_python_la_OBJECTS)
+libdns_python_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libdns_python_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libdns_python_la_SOURCES)
+DIST_SOURCES = $(libdns_python_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/jelte/repos/python-binding/missing --run aclocal-1.11
+AMTAR = ${SHELL} /home/jelte/repos/python-binding/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /home/jelte/repos/python-binding/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/jelte/repos/python-binding/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/jelte/repos/python-binding/missing --run automake-1.11
+AWK = gawk
+BOOST_INCLUDES = 
+BOOST_LDFLAGS = 
+BOOST_PYTHON_LIB = 
+BOOST_SYSTEM_LIB = -lboost_system-mt
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =  -I$(top_srcdir)/ext
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 -g -Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare -fPIC
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DSYMUTIL = 
+DUMPBIN = 
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+FGREP = /bin/grep -F
+GENHTML = 
+GREP = /bin/grep
+GTEST_CONFIG = 
+GTEST_INCLUDES = 
+GTEST_LDADD = 
+GTEST_LDFLAGS = 
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LCOV = 
+LD = /usr/bin/ld
+LDFLAGS =   -L/usr/lib/python3.1/config     
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIPO = 
+LN_S = ln -s
+LTLIBOBJS = 
+MAKEINFO = ${SHELL} /home/jelte/repos/python-binding/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+NM = /usr/bin/nm -B
+NMEDIT = 
+OBJDUMP = objdump
+OBJEXT = o
+OTOOL = 
+OTOOL64 = 
+PACKAGE = bind10-devel
+PACKAGE_BUGREPORT = bind10-bugs@isc.org
+PACKAGE_NAME = bind10-devel
+PACKAGE_STRING = bind10-devel 20100318
+PACKAGE_TARNAME = bind10-devel
+PACKAGE_URL = 
+PACKAGE_VERSION = 20100318
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PYTHON = /usr/bin/python3
+PYTHON_EXEC_PREFIX = ${exec_prefix}
+PYTHON_INCLUDES = -I/usr/include/python3.1 -I/usr/include/python3.1
+PYTHON_LDFLAGS =  -L/usr/lib/python3.1/config     
+PYTHON_LIB = -lpython3.1
+PYTHON_PLATFORM = linux2
+PYTHON_PREFIX = ${prefix}
+PYTHON_VERSION = 3.1
+RANLIB = ranlib
+SED = /bin/sed
+SET_MAKE = 
+SHELL = /bin/bash
+SQLITE_CFLAGS =  
+SQLITE_LIBS = -lsqlite3  
+STRIP = strip
+USE_LCOV = no
+VERSION = 20100318
+abs_builddir = /home/jelte/repos/python-binding/src/lib/dns/python
+abs_srcdir = /home/jelte/repos/python-binding/src/lib/dns/python
+abs_top_builddir = /home/jelte/repos/python-binding
+abs_top_srcdir = /home/jelte/repos/python-binding
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_DUMPBIN = 
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = i686-pc-linux-gnu
+build_alias = 
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = i686-pc-linux-gnu
+host_alias = 
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/jelte/repos/python-binding/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+lt_ECHO = echo
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+pkgpyexecdir = ${pyexecdir}/bind10-devel
+pkgpythondir = ${pythondir}/bind10-devel
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+pyexecdir = ${exec_prefix}/lib/python3.1/dist-packages
+pythondir = ${prefix}/lib/python3.1/dist-packages
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_build_prefix = ../../../../
+top_builddir = ../../../..
+top_srcdir = ../../../..
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+
+#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
+#libdns_python_name_la_SOURCES = name_python.cc
+#libdns_python_name_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_name_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
+lib_LTLIBRARIES = libdns_python.la
+libdns_python_la_SOURCES = libdns_python.cc libdns_python_common.cc
+libdns_python_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+
+#libdns_python_rrset_la_SOURCES = rrset_python.cc
+#libdns_python_rrset_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_rrset_la_LDFLAGS = $(PYTHON_LDFLAGS) libdns_python_name.la
+
+#libdns_python_rrset_la_SOURCES = rrset_python.cc
+#libdns_python_rrset_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_rrset_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+# Python prefers .so, while some OSes (specifically MacOS) use a different
+# suffix for dynamic objects.  -module is necessary to work this around.
+libdns_python_la_LDFLAGS = $(PYTHON_LDFLAGS) -module
+libdns_python_la_LIBADD = $(top_builddir)/src/lib/dns/libdns.la \
+	$(top_builddir)/src/lib/exceptions/libexceptions.la \
+	$(PYTHON_LIB)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/dns/python/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/lib/dns/python/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libdns_python.la: $(libdns_python_la_OBJECTS) $(libdns_python_la_DEPENDENCIES) 
+	$(libdns_python_la_LINK) -rpath $(libdir) $(libdns_python_la_OBJECTS) $(libdns_python_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+include ./$(DEPDIR)/libdns_python_la-libdns_python.Plo
+include ./$(DEPDIR)/libdns_python_la-libdns_python_common.Plo
+
+.cc.o:
+	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#	source='$<' object='$@' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#	source='$<' object='$@' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+#	source='$<' object='$@' libtool=yes \
+#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#	$(LTCXXCOMPILE) -c -o $@ $<
+
+libdns_python_la-libdns_python.lo: libdns_python.cc
+	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libdns_python_la-libdns_python.lo -MD -MP -MF $(DEPDIR)/libdns_python_la-libdns_python.Tpo -c -o libdns_python_la-libdns_python.lo `test -f 'libdns_python.cc' || echo '$(srcdir)/'`libdns_python.cc
+	$(am__mv) $(DEPDIR)/libdns_python_la-libdns_python.Tpo $(DEPDIR)/libdns_python_la-libdns_python.Plo
+#	source='libdns_python.cc' object='libdns_python_la-libdns_python.lo' libtool=yes \
+#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libdns_python_la-libdns_python.lo `test -f 'libdns_python.cc' || echo '$(srcdir)/'`libdns_python.cc
+
+libdns_python_la-libdns_python_common.lo: libdns_python_common.cc
+	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libdns_python_la-libdns_python_common.lo -MD -MP -MF $(DEPDIR)/libdns_python_la-libdns_python_common.Tpo -c -o libdns_python_la-libdns_python_common.lo `test -f 'libdns_python_common.cc' || echo '$(srcdir)/'`libdns_python_common.cc
+	$(am__mv) $(DEPDIR)/libdns_python_la-libdns_python_common.Tpo $(DEPDIR)/libdns_python_la-libdns_python_common.Plo
+#	source='libdns_python_common.cc' object='libdns_python_la-libdns_python_common.lo' libtool=yes \
+#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libdns_python_la-libdns_python_common.lo `test -f 'libdns_python_common.cc' || echo '$(srcdir)/'`libdns_python_common.cc
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 27 - 0
src/lib/dns/python/Makefile.am

@@ -0,0 +1,27 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+
+#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
+#libdns_python_name_la_SOURCES = name_python.cc
+#libdns_python_name_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_name_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
+lib_LTLIBRARIES = libdns_python.la
+libdns_python_la_SOURCES = libdns_python.cc libdns_python_common.cc
+libdns_python_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+libdns_python_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+#libdns_python_rrset_la_SOURCES = rrset_python.cc
+#libdns_python_rrset_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_rrset_la_LDFLAGS = $(PYTHON_LDFLAGS) libdns_python_name.la
+
+#libdns_python_rrset_la_SOURCES = rrset_python.cc
+#libdns_python_rrset_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_rrset_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+# Python prefers .so, while some OSes (specifically MacOS) use a different
+# suffix for dynamic objects.  -module is necessary to work this around.
+libdns_python_la_LDFLAGS += -module
+libdns_python_la_LIBADD = $(top_builddir)/src/lib/dns/libdns.la
+libdns_python_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+libdns_python_la_LIBADD += $(PYTHON_LIB)

+ 588 - 0
src/lib/dns/python/Makefile.in

@@ -0,0 +1,588 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/lib/dns/python
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libdns_python_la_DEPENDENCIES = $(top_builddir)/src/lib/dns/libdns.la \
+	$(top_builddir)/src/lib/exceptions/libexceptions.la \
+	$(am__DEPENDENCIES_1)
+am_libdns_python_la_OBJECTS = libdns_python_la-libdns_python.lo \
+	libdns_python_la-libdns_python_common.lo
+libdns_python_la_OBJECTS = $(am_libdns_python_la_OBJECTS)
+libdns_python_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(libdns_python_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libdns_python_la_SOURCES)
+DIST_SOURCES = $(libdns_python_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_INCLUDES = @BOOST_INCLUDES@
+BOOST_LDFLAGS = @BOOST_LDFLAGS@
+BOOST_PYTHON_LIB = @BOOST_PYTHON_LIB@
+BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GREP = @GREP@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_INCLUDES = @GTEST_INCLUDES@
+GTEST_LDADD = @GTEST_LDADD@
+GTEST_LDFLAGS = @GTEST_LDFLAGS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_LIB = @PYTHON_LIB@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SQLITE_CFLAGS = @SQLITE_CFLAGS@
+SQLITE_LIBS = @SQLITE_LIBS@
+STRIP = @STRIP@
+USE_LCOV = @USE_LCOV@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+
+#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
+#libdns_python_name_la_SOURCES = name_python.cc
+#libdns_python_name_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_name_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+#lib_LTLIBRARIES = libdns_python_name.la libdns_python_rrset.la
+lib_LTLIBRARIES = libdns_python.la
+libdns_python_la_SOURCES = libdns_python.cc libdns_python_common.cc
+libdns_python_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+
+#libdns_python_rrset_la_SOURCES = rrset_python.cc
+#libdns_python_rrset_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_rrset_la_LDFLAGS = $(PYTHON_LDFLAGS) libdns_python_name.la
+
+#libdns_python_rrset_la_SOURCES = rrset_python.cc
+#libdns_python_rrset_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+#libdns_python_rrset_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
+# Python prefers .so, while some OSes (specifically MacOS) use a different
+# suffix for dynamic objects.  -module is necessary to work this around.
+libdns_python_la_LDFLAGS = $(PYTHON_LDFLAGS) -module
+libdns_python_la_LIBADD = $(top_builddir)/src/lib/dns/libdns.la \
+	$(top_builddir)/src/lib/exceptions/libexceptions.la \
+	$(PYTHON_LIB)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/dns/python/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/lib/dns/python/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libdns_python.la: $(libdns_python_la_OBJECTS) $(libdns_python_la_DEPENDENCIES) 
+	$(libdns_python_la_LINK) -rpath $(libdir) $(libdns_python_la_OBJECTS) $(libdns_python_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_python_la-libdns_python.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdns_python_la-libdns_python_common.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+libdns_python_la-libdns_python.lo: libdns_python.cc
+@am__fastdepCXX_TRUE@	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libdns_python_la-libdns_python.lo -MD -MP -MF $(DEPDIR)/libdns_python_la-libdns_python.Tpo -c -o libdns_python_la-libdns_python.lo `test -f 'libdns_python.cc' || echo '$(srcdir)/'`libdns_python.cc
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/libdns_python_la-libdns_python.Tpo $(DEPDIR)/libdns_python_la-libdns_python.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='libdns_python.cc' object='libdns_python_la-libdns_python.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libdns_python_la-libdns_python.lo `test -f 'libdns_python.cc' || echo '$(srcdir)/'`libdns_python.cc
+
+libdns_python_la-libdns_python_common.lo: libdns_python_common.cc
+@am__fastdepCXX_TRUE@	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libdns_python_la-libdns_python_common.lo -MD -MP -MF $(DEPDIR)/libdns_python_la-libdns_python_common.Tpo -c -o libdns_python_la-libdns_python_common.lo `test -f 'libdns_python_common.cc' || echo '$(srcdir)/'`libdns_python_common.cc
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/libdns_python_la-libdns_python_common.Tpo $(DEPDIR)/libdns_python_la-libdns_python_common.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='libdns_python_common.cc' object='libdns_python_la-libdns_python_common.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LIBTOOL)  --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdns_python_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libdns_python_la-libdns_python_common.lo `test -f 'libdns_python_common.cc' || echo '$(srcdir)/'`libdns_python_common.cc
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:

+ 94 - 0
src/lib/dns/python/README

@@ -0,0 +1,94 @@
+
+This is a partial implementation of the python wrappers for isc::dns.
+
+Currently, when compiled the module is called libdns_python. If we
+decide to use it we will add a default import under lib/python/isc.
+
+To use it from the source tree, you must add src/lib/dns/python/.libs
+to your PYTHONPATH environment variable. Within python you can then use
+> import libdns_python
+> rrc = libdns_python.RRClass("IN")
+
+Notes:
+
+this implementation is far from complete; currently wrappers for the
+following classes are implemented:
+
+full (though we might add some conveniences later, like __str__):
+RRType, RRClass, RRTTL, Name, and MessageRenderer
+
+partial:
+RRset (doesn't have a way to iterate over rdata yet)
+Rdata (only the most basic support, you can create one from a type,
+class and string, and you can convert them to text, but that's about
+it).
+
+We did not implement the buffer classes; everywhere in the API where
+buffers are used, you can pass a bytearray object.
+
+The 'main' module is defined in libdns_python.cc.
+There is a libdns_python_common.[cc|h] for helper functions.
+
+Implementation notes:
+
+Writing wrappers for a lot of classes is mostly a case of repetition.
+There are a lot of things one must do, and that is why nearly everyone
+immediately and continually has the urge to make generators for this.
+
+We have added a little more documentation than is strictly necessary to
+rrclass.h, for reference to new readers.
+
+To keep it maintainable as the original API changes, we use two
+techniques;
+
+1. Full unittests. Or at least as full as possible. All unittests from
+   the C++ code will also appear in the python wrapper tests (currently
+   only done for rrtype and rrset as far as implemented), so if we
+   forget to update a wrapper our tests should fail.
+2. Structure. I have tried to structure the wrapper files as much as
+   possible, see below.
+
+Structure:
+
+Since we are moving a lot of wrappers into one module, the specific
+classes are split over several files, each one having the name of the
+original header file they are wrapping (e.g. the wrapper for name.h
+becomes name_python.cc).
+
+At the top we first declare any exceptions, constants, and enums. These
+are all called po_<C++-name> (the actual python name will be set once
+they are added to the module in the module inialization function).
+
+Each class needs a struct that contains a pointer to an instance of the
+object (and any helper data). We call these structs s_<C++ class name>.
+
+Then we declare (but not define!) all methods we will export to
+python. These are named <C++ class name>_<C++ method name>.
+
+We will also need an _init and _destroy function for all of these.
+
+After the function declarations we define the method array; this
+contains the name of the methods as they appear in python, the wrapping
+function here, and documentation strings.
+
+Next is the type description; this is used for the wrapper code to
+convert native classes from and to python objects, and defines
+type-specific pointers (for instance to the method table mentioned above,
+but also to a __str__ function should one be defined, how the object
+should behave when it is used as a Sequence, etc.). For most classes,
+almost all values here shall be NULL.
+This has the name <lowercase C++ class name>_type.
+
+After that we define the exported functions we defined earlier. In some
+cases these need the type we just defined, and the type needed the
+function names, so for consistency, all functions are defined after,
+but declared before the type.
+
+This is repeated for every class we export.
+
+Finally we define the function to add the class, constants, exceptions,
+and enums to the module. This function is called from the init function
+in libdns_python.cc, has the name
+initModulePart_<c++ class name>, returns a boolean
+(true on success, false on failure), and takes the module as a
+PyObject*.

+ 92 - 0
src/lib/dns/python/libdns_python.cc

@@ -0,0 +1,92 @@
+
+// Ok we want a lot of different parts of the DNS API in the python
+// module, but not one big 10000-line file.
+// So we split it up in several 'mini-modules'
+// These would be the same as a single module, except for
+// the init function, which has to be modified to a unique
+// name initModulePart_<name>, and return true/false instead of
+// NULL/*mod
+//
+// And of course care has to be taken that all identifiers be unique
+
+// 
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#include "config.h"
+
+#include <exceptions/exceptions.h>
+
+#include <dns/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+
+#include "libdns_python_common.h"
+
+//#include "buffer_python.cc"
+// order is important here! (TODO: document dependencies)
+#include "name_python.cc"
+#include "messagerenderer_python.cc"
+#include "rrclass_python.cc"
+#include "rrtype_python.cc"
+#include "rrttl_python.cc"
+#include "rdata_python.cc"
+#include "rrset_python.cc"
+
+//
+// Definition of the module
+//
+static PyModuleDef libdns_python = {
+    { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
+    "libdns_python",
+    "Python bindings for isc.dns",
+    -1,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+PyMODINIT_FUNC
+PyInit_libdns_python(void)
+{
+    PyObject *mod = PyModule_Create(&libdns_python);
+    if (mod == NULL) {
+        return NULL;
+    }
+
+    // for each part included above, we call its specific initializer
+
+    if (!initModulePart_Name(mod)) {
+        return NULL;
+    }
+
+    if (!initModulePart_MessageRenderer(mod)) {
+        return NULL;
+    }
+
+    if (!initModulePart_RRClass(mod)) {
+        return NULL;
+    }
+
+    if (!initModulePart_RRType(mod)) {
+        return NULL;
+    }
+
+    if (!initModulePart_RRTTL(mod)) {
+        return NULL;
+    }
+
+    if (!initModulePart_Rdata(mod)) {
+        return NULL;
+    }
+
+    if (!initModulePart_RRset(mod)) {
+        return NULL;
+    }
+
+    return mod;
+}
+

+ 48 - 0
src/lib/dns/python/libdns_python_common.cc

@@ -0,0 +1,48 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <Python.h>
+
+int
+readDataFromSequence(uint8_t *data, size_t len, PyObject* sequence)
+{
+    PyObject* el = NULL;
+    for (size_t i = 0; i < len; i++) {
+        el = PySequence_GetItem(sequence, 0);
+        if (!el) {
+            PyErr_SetString(PyExc_TypeError,
+                "sequence too short");
+            return -1;
+        }
+        if (PyLong_Check(el)) {
+            long l = PyLong_AsLong(el);
+            if (l < 0 || l > 255) {
+                PyErr_SetString(PyExc_TypeError,
+                    "number in fromWire sequence not between 0 and 255");
+                return -1;
+            }
+            data[i] = (uint8_t) PyLong_AsLong(el);
+            PySequence_DelItem(sequence, 0);
+        } else {
+            PyErr_SetString(PyExc_TypeError,
+                "not a number in fromWire sequence");
+            return -1;
+        }
+    }
+    return 0;
+}
+
+

+ 32 - 0
src/lib/dns/python/libdns_python_common.h

@@ -0,0 +1,32 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+
+//
+// Shared functions for python/c API
+//
+
+// This function reads 'bytes' from a sequence
+// This sequence can be anything that implements the Sequence interface,
+// but must consist of Numbers between 0 and 255 for every value.
+//
+// The data is stored in *data.
+// Data must be allocated and have at least len bytes available.
+//
+// The current implementation removes read items from the
+// head of the sequence (even if it fails it removes everything that
+// it successfully read)
+int readDataFromSequence(uint8_t *data, size_t len, PyObject* sequence);

+ 175 - 0
src/lib/dns/python/messagerenderer_python.cc

@@ -0,0 +1,175 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <dns/messagerenderer.h>
+
+// 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
+using namespace isc::dns;
+
+// MessageRenderer
+
+// since we don't use *Buffer in the python version (but work with
+// the already existing bytearray type where we use these custom buffers
+// in c++, we need to keep track of one here.
+typedef struct {
+    PyObject_HEAD
+    OutputBuffer* outputbuffer;
+    MessageRenderer* messagerenderer;
+} s_MessageRenderer;
+
+static int MessageRenderer_init(s_MessageRenderer* self);
+static void MessageRenderer_destroy(s_MessageRenderer* self);
+
+static PyObject* MessageRenderer_getData(s_MessageRenderer* self);
+static PyObject* MessageRenderer_getLength(s_MessageRenderer* self);
+static PyObject* MessageRenderer_isTruncated(s_MessageRenderer* self);
+static PyObject* MessageRenderer_getLengthLimit(s_MessageRenderer* self);
+
+static PyMethodDef MessageRenderer_methods[] = {
+    { "get_data", (PyCFunction)MessageRenderer_getData, METH_NOARGS, "Return the data" },
+    { "get_length", (PyCFunction)MessageRenderer_getLength, METH_NOARGS, "Return the length of the data" },
+    { "is_truncated", (PyCFunction)MessageRenderer_isTruncated, METH_NOARGS, "Returns True if the data is truncated" },
+    { "get_length_limit", (PyCFunction)MessageRenderer_getLengthLimit, METH_NOARGS, "Return the length limit of the data" },
+    { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject messagerenderer_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.MessageRenderer",
+    sizeof(s_MessageRenderer),                       /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)MessageRenderer_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 */
+    "C++ MessageRenderer Object",  /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    NULL,                               /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    MessageRenderer_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 */
+    (initproc)MessageRenderer_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+static int
+MessageRenderer_init(s_MessageRenderer* self)
+{
+    self->outputbuffer = new OutputBuffer(4096);
+    self->messagerenderer = new MessageRenderer(*self->outputbuffer);
+    return 0;
+}
+
+static void
+MessageRenderer_destroy(s_MessageRenderer* self)
+{
+    delete self->messagerenderer;
+    delete self->outputbuffer;
+    self->messagerenderer = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+MessageRenderer_getData(s_MessageRenderer* self)
+{
+    return Py_BuildValue("y#", self->messagerenderer->getData(), self->messagerenderer->getLength());
+}
+
+static PyObject*
+MessageRenderer_getLength(s_MessageRenderer* self)
+{
+    return Py_BuildValue("I", self->messagerenderer->getLength());
+}
+
+static PyObject*
+MessageRenderer_isTruncated(s_MessageRenderer* self)
+{
+    if (self->messagerenderer->isTruncated())
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+
+static PyObject*
+MessageRenderer_getLengthLimit(s_MessageRenderer* self)
+{
+    return Py_BuildValue("I", self->messagerenderer->getLengthLimit());
+}
+
+// end of MessageRenderer
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_MessageRenderer(PyObject* mod)
+{
+    // Add the exceptions to the module
+
+    // Add the enums to the module
+
+    // Add the constants to the module
+
+    // Add the classes to the module
+    // We initialize the static description object with PyType_Ready(),
+    // then add it to the module
+
+    // NameComparisonResult
+    if (PyType_Ready(&messagerenderer_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&messagerenderer_type);
+    PyModule_AddObject(mod, "MessageRenderer",
+                       (PyObject*) &messagerenderer_type);
+    
+    return true;
+}
+
+

+ 651 - 0
src/lib/dns/python/name_python.cc

@@ -0,0 +1,651 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the module init at the
+// end
+//
+static PyObject* po_EmptyLabel;
+static PyObject* po_TooLongName;
+static PyObject* po_TooLongLabel;
+static PyObject* po_BadLabelType;
+static PyObject* po_BadEscape;
+static PyObject* po_IncompleteName;
+static PyObject* po_InvalidBufferPosition;
+static PyObject* po_DNSMessageFORMERR;
+// This one's for our 'general' exception
+// TODO: does this need an according general class?
+// should we replace it with some more direct base exception?
+static PyObject* po_IscException;
+
+//
+// Declaration of enums
+// Initialization and addition of these go in the module init at the
+// end
+//
+static PyObject* po_NameRelation;
+
+//
+// Declaration of class constants
+// Initialization and addition of these go in the module init at the
+// end
+//
+static PyObject* po_MAX_WIRE;
+static PyObject* po_MAX_LABELS;
+static PyObject* po_MAX_LABELLEN;
+static PyObject* po_MAX_COMPRESS_POINTER;
+static PyObject* po_COMPRESS_POINTER_MARK8;
+static PyObject* po_COMPRESS_POINTER_MARK16;
+static PyObject* po_ROOT_NAME;
+
+
+
+//
+// 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
+using namespace isc::dns;
+
+// NameComparisonResult
+typedef struct {
+    PyObject_HEAD
+    isc::dns::NameComparisonResult* ncr;
+} s_NameComparisonResult;
+
+static int NameComparisonResult_init(s_NameComparisonResult* self UNUSED_PARAM, PyObject* args UNUSED_PARAM);
+static void NameComparisonResult_destroy(s_NameComparisonResult* self);
+static PyObject* NameComparisonResult_getOrder(s_NameComparisonResult* self);
+static PyObject* NameComparisonResult_getCommonLabels(s_NameComparisonResult* self);
+static PyObject* NameComparisonResult_getRelation(s_NameComparisonResult* self);
+
+static PyMethodDef NameComparisonResult_methods[] = {
+    { "getOrder", (PyCFunction)NameComparisonResult_getOrder, METH_NOARGS, "Return the order" },
+    { "getCommonLabels", (PyCFunction)NameComparisonResult_getCommonLabels, METH_NOARGS, "Return the number of common labels" },
+    { "getRelation", (PyCFunction)NameComparisonResult_getRelation, METH_NOARGS, "Return the relation" },
+    { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject name_comparison_result_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.NameComparisonResult",
+    sizeof(s_NameComparisonResult),                       /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)NameComparisonResult_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 */
+    "C++ NameComparisonResult Object",  /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    NULL,                               /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    NameComparisonResult_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 */
+    (initproc)NameComparisonResult_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+// TODO: is there also a way to just not define it?
+static int
+NameComparisonResult_init(s_NameComparisonResult* self UNUSED_PARAM, PyObject* args UNUSED_PARAM) {
+    PyErr_SetString(PyExc_NotImplementedError,
+                    "NameComparisonResult can't be built directly");
+    return -1;
+}
+
+static void
+NameComparisonResult_destroy(s_NameComparisonResult* self) {
+    delete self->ncr;
+    self->ncr = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject* 
+NameComparisonResult_getOrder(s_NameComparisonResult* self) {
+    return Py_BuildValue("i", self->ncr->getOrder());
+}
+
+static PyObject* 
+NameComparisonResult_getCommonLabels(s_NameComparisonResult* self) {
+    return Py_BuildValue("I", self->ncr->getCommonLabels());
+}
+
+static PyObject* 
+NameComparisonResult_getRelation(s_NameComparisonResult* self) {
+    return Py_BuildValue("I", self->ncr->getRelation());
+}
+
+// end of NameComparisonResult
+
+// Name
+typedef struct {
+    PyObject_HEAD
+    isc::dns::Name* name;
+    size_t position;
+} s_Name;
+
+static int Name_init(s_Name* self, PyObject* args);
+static void Name_destroy(s_Name* self);
+
+static PyObject* Name_toWire(s_Name* self);
+static PyObject* Name_toText(s_Name* self);
+static PyObject* Name_getLabelCount(s_Name* self);
+static PyObject* Name_at(s_Name* self, PyObject* args);
+static PyObject* Name_getLength(s_Name* self);
+
+static PyObject* Name_compare(s_Name* self, PyObject* args);
+static PyObject* Name_equals(s_Name* self, PyObject* args);
+
+static PyObject* Name_richcmp(s_Name* n1, s_Name* n2, int op);
+static PyObject* Name_split(s_Name* self, PyObject* args);
+static PyObject* Name_reverse(s_Name* self);
+static PyObject* Name_concatenate(s_Name* self, PyObject* args);
+static PyObject* Name_downcase(s_Name* self);
+static PyObject* Name_isWildCard(s_Name* self);
+
+static PyMethodDef Name_methods[] = {
+    { "at", (PyCFunction)Name_at, METH_VARARGS, "Return the int value of the name data at the specified position" },
+    { "get_length", (PyCFunction)Name_getLength, METH_NOARGS, "Return the length" },
+    { "get_labelcount", (PyCFunction)Name_getLabelCount, METH_NOARGS, "Return the number of labels" },
+    { "to_text", (PyCFunction)Name_toText, METH_NOARGS, "Return the string representation" },
+    { "to_wire", (PyCFunction)Name_toWire, METH_NOARGS, "Return the wire format" },
+    { "compare", (PyCFunction)Name_compare, METH_VARARGS, "Compare" },
+    { "equals", (PyCFunction)Name_equals, METH_VARARGS, "Equals" },
+    { "split", (PyCFunction)Name_split, METH_VARARGS, "split" },
+    { "reverse", (PyCFunction)Name_reverse, METH_NOARGS, "reverse" },
+    { "concatenate", (PyCFunction)Name_concatenate, METH_VARARGS, "concatenate" },
+    { "downcase", (PyCFunction)Name_downcase, METH_NOARGS, "downcase" },
+    { "is_wildcard", (PyCFunction)Name_isWildCard, METH_NOARGS, "isWildCard" },
+    { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject name_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.Name",
+    sizeof(s_Name),                       /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)Name_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 */
+    "C++ Name Object",  /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    (richcmpfunc)Name_richcmp,                               /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    Name_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 */
+    (initproc)Name_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+
+static int
+Name_init(s_Name* self, PyObject* args)
+{
+    const char* s;
+    PyObject* downcase = Py_False;
+
+    /* fromText */
+    if (PyArg_ParseTuple(args, "s|O!", &s, &PyBool_Type, &downcase)) {
+        try {
+            const std::string n(s);
+
+            self->name = new Name(n, downcase == Py_True);
+            self->position = 0;
+        } catch (EmptyLabel) {
+            PyErr_SetString(po_EmptyLabel, "EmptyLabel");
+            return -1;
+        } catch (TooLongLabel) {
+            PyErr_SetString(po_TooLongLabel, "TooLongLabel");
+            return -1;
+        } catch (BadLabelType) {
+            PyErr_SetString(po_BadLabelType, "BadLabelType");
+            return -1;
+        } catch (BadEscape) {
+            PyErr_SetString(po_BadEscape, "BadEscape");
+            return -1;
+        } catch (TooLongName) {
+            PyErr_SetString(po_TooLongName, "TooLongName");
+            return -1;
+        } catch (IncompleteName) {
+            PyErr_SetString(po_IncompleteName, "IncompleteName");
+            return -1;
+#ifdef CATCHMEMERR
+        } catch (std::bad_alloc) {
+            PyErr_NoMemory();
+            return -1;
+#endif
+        } catch (...) {
+            PyErr_SetString(po_IscException, "Unexpected?!");
+            return -1;
+        }
+        return 0;
+    }
+    PyErr_Clear();
+
+    const char* b;
+    Py_ssize_t len;
+    unsigned int position;
+
+    /* fromWire */
+    if (PyArg_ParseTuple(args, "y#I|O!", &b, &len, &position,
+                         &PyBool_Type, &downcase)) {
+        try {
+            InputBuffer buffer(b, len);
+
+            buffer.setPosition(position);
+            self->name = new Name(buffer, downcase == Py_True);
+            self->position = buffer.getPosition();
+        } catch (InvalidBufferPosition) {
+            PyErr_SetString(po_InvalidBufferPosition,
+                            "InvalidBufferPosition");
+            return -1;
+        } catch (TooLongName) {
+            PyErr_SetString(po_TooLongName, "TooLongName");
+            return -1;
+        } catch (BadLabelType) {
+            PyErr_SetString(po_BadLabelType, "BadLabelType");
+            return -1;
+        } catch (DNSMessageFORMERR) {
+            PyErr_SetString(po_DNSMessageFORMERR, "DNSMessageFORMERR");
+            return -1;
+        } catch (IncompleteName) {
+            PyErr_SetString(po_IncompleteName, "IncompleteName");
+            return -1;
+#ifdef CATCHMEMERR
+        } catch (std::bad_alloc) {
+            PyErr_NoMemory();
+            return -1;
+#endif
+        } catch (...) {
+            PyErr_SetString(po_IscException, "Unexpected?!");
+            return -1;
+        }
+        return 0;
+    }
+
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "fromText and fromWire Name constructors don't match");
+    return -1;
+}
+
+static void
+Name_destroy(s_Name* self)
+{
+    delete self->name;
+    self->name = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+Name_at(s_Name* self, PyObject* args)
+{
+    size_t pos;
+    if (!PyArg_ParseTuple(args, "i", &pos)) {
+        return NULL;
+    }
+    try {
+        return Py_BuildValue("i", self->name->at(pos));
+    } catch (isc::OutOfRange oor) {
+        PyErr_SetString(PyExc_IndexError,
+                        "name index out of range");
+        return NULL;
+    }
+}
+
+static PyObject*
+Name_getLength(s_Name* self)
+{
+    return Py_BuildValue("i", self->name->getLength());
+}
+
+static PyObject*
+Name_getLabelCount(s_Name* self)
+{
+    return Py_BuildValue("i", self->name->getLabelCount());
+}
+
+static PyObject*
+Name_toText(s_Name* self)
+{
+    return Py_BuildValue("s", self->name->toText().c_str());
+}
+
+// XX TODO: renderer and direct versions
+static PyObject*
+Name_toWire(s_Name* self)
+{
+    OutputBuffer buffer(255);
+
+    self->name->toWire(buffer);
+    return Py_BuildValue("y#", buffer.getData(),
+                         (Py_ssize_t) buffer.getLength());
+}
+
+static PyObject*
+Name_compare(s_Name* self, PyObject* args) {
+    s_Name* other;
+
+    if (!PyArg_ParseTuple(args, "O!", &name_type, (PyObject* *) &other))
+        return NULL;
+
+    s_NameComparisonResult* ret = PyObject_New(s_NameComparisonResult, &name_comparison_result_type);
+    if (ret != NULL) {
+        ret->ncr = new NameComparisonResult(
+            self->name->compare(*other->name));
+        if (ret->ncr == NULL) {
+            Py_DECREF(ret);
+            return NULL;
+        }
+    }
+    return (PyObject*) ret;
+}
+
+static PyObject* 
+Name_equals(s_Name* self, PyObject* args) {
+    s_Name* other;
+
+    if (!PyArg_ParseTuple(args, "O!", &name_type, (PyObject* *) &other))
+        return NULL;
+
+    if (self->name->equals(*other->name))
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+
+static PyObject* 
+Name_split(s_Name* self, PyObject* args)
+{
+    unsigned int first, n;
+
+    if (!PyArg_ParseTuple(args, "II", &first, &n))
+        return NULL;
+
+    s_Name* ret = PyObject_New(s_Name, &name_type);
+    if (ret != NULL) {
+        ret->name = NULL;
+        try {
+            ret->name = new Name(self->name->split(first, n));
+        } catch(isc::OutOfRange oor) {
+            PyErr_SetString(PyExc_IndexError, oor.what());
+            ret->name = NULL;
+        }
+        if (ret->name == NULL) {
+            Py_DECREF(ret);
+            return NULL;
+        }
+    }
+    return (PyObject*) ret;
+}
+
+static PyObject* 
+Name_richcmp(s_Name* n1, s_Name* n2, int op)
+{
+    bool c;
+
+    switch (op) {
+    case Py_LT:
+        c = n1->name->lthan(*n2->name);
+        break;
+    case Py_LE:
+        c = n1->name->leq(*n2->name);
+        break;
+    case Py_EQ:
+        c = n1->name->equals(*n2->name);
+        break;
+    case Py_NE:
+        c = n1->name->nequals(*n2->name);
+        break;
+    case Py_GT:
+        c = n1->name->gthan(*n2->name);
+        break;
+    case Py_GE:
+        c = n1->name->geq(*n2->name);
+        break;
+    default:
+        assert(0);              // XXX: should trigger an exception
+    }
+    if (c)
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+
+static PyObject*
+Name_reverse(s_Name* self)
+{
+    s_Name* ret = PyObject_New(s_Name, &name_type);
+
+    if (ret != NULL) {
+        ret->name = new Name(self->name->reverse());
+        if (ret->name == NULL) {
+            Py_DECREF(ret);
+            return NULL;
+        }
+    }
+    return (PyObject*) ret;
+}
+
+static PyObject*
+Name_concatenate(s_Name* self, PyObject* args)
+{
+    s_Name* other;
+
+    if (!PyArg_ParseTuple(args, "O!", &name_type, (PyObject**) &other))
+        return NULL;
+
+    s_Name* ret = PyObject_New(s_Name, &name_type);
+    if (ret != NULL) {
+        try {
+            ret->name = new Name(self->name->concatenate(*other->name));
+        } catch (isc::dns::TooLongName tln) {
+            PyErr_SetString(PyExc_IndexError, tln.what());
+            ret->name = NULL;
+        }
+        if (ret->name == NULL) {
+            Py_DECREF(ret);
+            return NULL;
+        }
+    }
+    return (PyObject*) ret;
+}
+
+static PyObject*
+Name_downcase(s_Name* self)
+{
+    self->name->downcase();
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+Name_isWildCard(s_Name* self)
+{
+    if (self->name->isWildcard()) {
+        Py_RETURN_TRUE;
+    } else {
+        Py_RETURN_FALSE;
+    }
+}
+// end of Name
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_Name(PyObject* mod)
+{
+    // Add the exceptions to the module
+    po_EmptyLabel = PyErr_NewException("libdns_python.EmptyLabel", NULL, NULL);
+    Py_INCREF(po_EmptyLabel);
+    PyModule_AddObject(mod, "EmptyLabel", po_EmptyLabel);
+
+    po_TooLongName = PyErr_NewException("libdns_python.TooLongName", NULL, NULL);
+    Py_INCREF(po_TooLongName);
+    PyModule_AddObject(mod, "TooLongName", po_TooLongName);
+
+    po_TooLongLabel = PyErr_NewException("libdns_python.TooLongLabel", NULL, NULL);
+    Py_INCREF(po_TooLongLabel);
+    PyModule_AddObject(mod, "TooLongLabel", po_TooLongLabel);
+
+    po_BadLabelType = PyErr_NewException("libdns_python.BadLabelType", NULL, NULL);
+    Py_INCREF(po_BadLabelType);
+    PyModule_AddObject(mod, "BadLabelType", po_BadLabelType);
+
+    po_BadEscape = PyErr_NewException("libdns_python.BadEscape", NULL, NULL);
+    Py_INCREF(po_BadEscape);
+    PyModule_AddObject(mod, "BadEscape", po_BadEscape);
+
+    po_IncompleteName = PyErr_NewException("libdns_python.IncompleteName", NULL, NULL);
+    Py_INCREF(po_IncompleteName);
+    PyModule_AddObject(mod, "IncompleteName", po_IncompleteName);
+
+    po_InvalidBufferPosition = PyErr_NewException("libdns_python.InvalidBufferPosition", NULL, NULL);
+    Py_INCREF(po_InvalidBufferPosition);
+    PyModule_AddObject(mod, "InvalidBufferPosition", po_InvalidBufferPosition);
+
+    po_DNSMessageFORMERR = PyErr_NewException("libdns_python.DNSMessageFORMERR", NULL, NULL);
+    Py_INCREF(po_DNSMessageFORMERR);
+    PyModule_AddObject(mod, "DNSMessageFORMERR", po_DNSMessageFORMERR);
+
+    po_IscException = PyErr_NewException("libdns_python.IscException", NULL, NULL);
+    Py_INCREF(po_IncompleteName);
+    PyModule_AddObject(mod, "IscException", po_IscException);
+
+    // Add the enums to the module
+    po_NameRelation = Py_BuildValue("{i:s,i:s,i:s,i:s}",
+                                    0, "SUPERDOMAIN",
+                                    1, "SUBDOMAIN",
+                                    2, "EQUAL",
+                                    3, "COMMONANCESTOR");
+    Py_INCREF(po_NameRelation);
+    PyModule_AddObject(mod, "NameRelation", po_NameRelation);
+
+    // Add the constants to the module
+    po_MAX_WIRE = Py_BuildValue("I", 255U);
+    Py_INCREF(po_MAX_WIRE);
+    PyModule_AddObject(mod, "MAX_WIRE", po_MAX_WIRE);
+    po_MAX_LABELS = Py_BuildValue("I", 128U);
+    Py_INCREF(po_MAX_LABELS);
+    PyModule_AddObject(mod, "MAX_LABELS", po_MAX_LABELS);
+    po_MAX_LABELLEN = Py_BuildValue("I", 63U);
+    Py_INCREF(po_MAX_LABELLEN);
+    PyModule_AddObject(mod, "MAX_LABELLEN", po_MAX_LABELLEN);
+    po_MAX_COMPRESS_POINTER = Py_BuildValue("I", 0x3fffU);
+    Py_INCREF(po_MAX_COMPRESS_POINTER);
+    PyModule_AddObject(mod, "MAX_COMPRESS_POINTER", po_MAX_COMPRESS_POINTER);
+    po_COMPRESS_POINTER_MARK8 = Py_BuildValue("I", 0xc0U);
+    Py_INCREF(po_COMPRESS_POINTER_MARK8);
+    PyModule_AddObject(mod, "COMPRESS_POINTER_MARK8", po_COMPRESS_POINTER_MARK8);
+    po_COMPRESS_POINTER_MARK16 = Py_BuildValue("I", 0xc000U);
+    Py_INCREF(po_COMPRESS_POINTER_MARK16);
+    PyModule_AddObject(mod, "COMPRESS_POINTER_MARK16", po_COMPRESS_POINTER_MARK16);
+    s_Name* root_name = PyObject_New(s_Name, &name_type);
+    root_name->name = new Name(".");
+    po_ROOT_NAME = (PyObject*) root_name;
+    Py_INCREF(po_ROOT_NAME);
+    PyModule_AddObject(mod, "ROOT_NAME", po_ROOT_NAME);
+
+    // Add the classes to the module
+    // We initialize the static description object with PyType_Ready(),
+    // then add it to the module
+
+    // NameComparisonResult
+    if (PyType_Ready(&name_comparison_result_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&name_comparison_result_type);
+    PyModule_AddObject(mod, "NameComparisonResult",
+                       (PyObject*) &name_comparison_result_type);
+    
+    if (PyType_Ready(&name_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&name_type);
+    PyModule_AddObject(mod, "Name",
+                       (PyObject*) &name_type);
+    
+    return true;
+}

+ 228 - 0
src/lib/dns/python/rdata_python.cc

@@ -0,0 +1,228 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <dns/rdata.h>
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function at the end of this file
+//
+static PyObject* po_InvalidRdataLength;
+static PyObject* po_InvalidRdataText;
+static PyObject* po_CharStringTooLong;
+
+//
+// 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
+
+//
+// Rdata
+//
+
+// The s_* Class simply coverst one instantiation of the object
+typedef struct {
+    PyObject_HEAD
+    RdataPtr rdata;
+} s_Rdata;
+
+//
+// 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
+static int Rdata_init(s_Rdata* self, PyObject* args);
+static void Rdata_destroy(s_Rdata* self);
+
+// These are the functions we export
+static PyObject* Rdata_toText(s_Rdata* self);
+// This is a second version of toText, we need one where the argument
+// is a PyObject*, for the str() function in python.
+static PyObject* Rdata_str(PyObject* self);
+static PyObject* Rdata_toWire(s_Rdata* self, PyObject* args);
+
+// 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
+static PyMethodDef Rdata_methods[] = {
+    { "to_text", (PyCFunction)Rdata_toText, METH_NOARGS, "Return the string representation" },
+    { "to_wire", (PyCFunction)Rdata_toWire, METH_VARARGS, "wire format" },
+    { NULL, NULL, 0, NULL }
+};
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_Rdata
+// Most of the functions are not actually implemented and NULL here.
+static PyTypeObject rdata_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.Rdata",
+    sizeof(s_Rdata),                  /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)Rdata_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 */
+    Rdata_str,                               /* tp_str */
+    NULL,                               /* tp_getattro */
+    NULL,                               /* tp_setattro */
+    NULL,                               /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    "C++ Rdata Object",                 /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    NULL,                               /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    Rdata_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 */
+    (initproc)Rdata_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+static int
+Rdata_init(s_Rdata* self, PyObject* args)
+{
+    s_RRType* rrtype;
+    s_RRClass* rrclass;
+    const char* s;
+    
+    if (PyArg_ParseTuple(args, "O!O!s", &rrtype_type, &rrtype,
+                                        &rrclass_type, &rrclass,
+                                        &s, &s
+       )) {
+        const std::string str(s);
+        self->rdata = createRdata(*rrtype->rrtype, *rrclass->rrclass, s);
+        return 0;
+    }
+
+    return -1;
+}
+
+static void
+Rdata_destroy(s_Rdata* self)
+{
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+Rdata_toText(s_Rdata* self)
+{
+    // Py_BuildValue makes python objects from native data
+    return Py_BuildValue("s", self->rdata->toText().c_str());
+}
+
+static PyObject*
+Rdata_str(PyObject* self)
+{
+    // Simply call the to_text method we already defined
+    return PyObject_CallMethod(self, (char*)"to_text", (char*)"");
+}
+
+static PyObject*
+Rdata_toWire(s_Rdata* self, PyObject* args)
+{
+    PyObject* bytes;
+    s_MessageRenderer* mr;
+    
+    if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+        PyObject* bytes_o = bytes;
+        
+        OutputBuffer buffer(2);
+        self->rdata->toWire(buffer);
+        PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
+        PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+        // We need to release the object we temporarily created here
+        // to prevent memory leak
+        Py_DECREF(n);
+        return result;
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+        self->rdata->toWire(*mr->messagerenderer);
+        // If we return NULL it is seen as an error, so use this for
+        // None returns
+        Py_RETURN_NONE;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "toWire argument must be a sequence object or a MessageRenderer");
+    return NULL;
+}
+
+// end of Rdata
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_Rdata(PyObject* mod)
+{
+    // Add the exceptions to the module
+    po_InvalidRdataLength = PyErr_NewException("libdns_python.InvalidRdataLength", NULL, NULL);
+    Py_INCREF(po_InvalidRdataLength);
+    PyModule_AddObject(mod, "InvalidRdataLength", po_InvalidRdataLength);
+    po_InvalidRdataText = PyErr_NewException("libdns_python.InvalidRdataText", NULL, NULL);
+    Py_INCREF(po_InvalidRdataText);
+    PyModule_AddObject(mod, "InvalidRdataText", po_InvalidRdataText);
+    po_CharStringTooLong = PyErr_NewException("libdns_python.CharStringTooLong", NULL, NULL);
+    Py_INCREF(po_CharStringTooLong);
+    PyModule_AddObject(mod, "CharStringTooLong", po_CharStringTooLong);
+
+    // 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(&rdata_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&rdata_type);
+    PyModule_AddObject(mod, "Rdata",
+                       (PyObject*) &rdata_type);
+    
+    return true;
+}

+ 306 - 0
src/lib/dns/python/rrclass_python.cc

@@ -0,0 +1,306 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <dns/rrclass.h>
+using namespace isc::dns;
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function at the end of this file
+//
+static PyObject* po_InvalidRRClass;
+static PyObject* po_IncompleteRRClass;
+
+//
+// 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
+
+//
+// RRClass
+//
+
+// The s_* Class simply coverst one instantiation of the object
+typedef struct {
+    PyObject_HEAD
+    RRClass* rrclass;
+} s_RRClass;
+
+//
+// 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
+static int RRClass_init(s_RRClass* self, PyObject* args);
+static void RRClass_destroy(s_RRClass* self);
+
+// These are the functions we export
+static PyObject* RRClass_toText(s_RRClass* self);
+// This is a second version of toText, we need one where the argument
+// is a PyObject*, for the str() function in python.
+static PyObject* RRClass_str(PyObject* self);
+static PyObject* RRClass_toWire(s_RRClass* self, PyObject* args);
+static PyObject* RRClass_getCode(s_RRClass* self);
+static PyObject* RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op);
+
+// 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
+static PyMethodDef RRClass_methods[] = {
+    { "to_text", (PyCFunction)RRClass_toText, METH_NOARGS, "Return the string representation" },
+    { "to_wire", (PyCFunction)RRClass_toWire, METH_VARARGS, "to wire format" },
+    { "get_code", (PyCFunction)RRClass_getCode, METH_NOARGS, "Return the class code as an integer" },
+    { NULL, NULL, 0, NULL }
+};
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_RRClass
+// Most of the functions are not actually implemented and NULL here.
+static PyTypeObject rrclass_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.RRClass",
+    sizeof(s_RRClass),                  /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)RRClass_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 */
+    RRClass_str,                               /* tp_str */
+    NULL,                               /* tp_getattro */
+    NULL,                               /* tp_setattro */
+    NULL,                               /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    "C++ RRClass Object",               /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    (richcmpfunc)RRClass_richcmp,       /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    RRClass_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 */
+    (initproc)RRClass_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+static int
+RRClass_init(s_RRClass* self, PyObject* args)
+{
+    const char* s;
+    unsigned int i;
+    PyObject* bytes = NULL;
+    // The constructor argument can be a string ("IN"), an integer (1),
+    // or a sequence of numbers between 0 and 255 (wire code)
+
+    // Note that PyArg_ParseType can set PyError, and we need to clear
+    // that if we try several like here. Otherwise the *next* python
+    // call will suddenly appear to throw an exception.
+    // (the way to do exceptions is to set PyErr and return -1)
+    try {
+        if (PyArg_ParseTuple(args, "s", &s)) {
+            self->rrclass = new RRClass(s);
+            return 0;
+        } else if (PyArg_ParseTuple(args, "I", &i)) {
+            PyErr_Clear();
+            if (i > 65535) {
+                PyErr_SetString(po_InvalidRRClass, "Class number too high");
+                return -1;
+            }
+            self->rrclass = new RRClass(i);
+            return 0;
+        } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+            uint8_t data[2];
+            int result = readDataFromSequence(data, 2, bytes);
+            if (result != 0) {
+                return result;
+            }
+            InputBuffer ib(data, 2);
+            self->rrclass = new RRClass(ib);
+            PyErr_Clear();
+            return 0;
+        }
+    } catch (IncompleteRRClass icc) {
+        // Ok so one of our functions has thrown a C++ exception.
+        // We need to translate that to a Python Exception
+        // First clear any existing error that was set
+        PyErr_Clear();
+        // Now set our own exception
+        PyErr_SetString(po_InvalidRRClass, icc.what());
+        // And return negative
+        return -1;
+    } catch (InvalidRRClass ic) {
+        PyErr_Clear();
+        PyErr_SetString(po_InvalidRRClass, ic.what());
+        return -1;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "no valid type in constructor argument");
+    return -1;
+}
+
+static void
+RRClass_destroy(s_RRClass* self)
+{
+    if (self->rrclass != NULL)
+        delete self->rrclass;
+    self->rrclass = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+RRClass_toText(s_RRClass* self)
+{
+    // Py_BuildValue makes python objects from native data
+    return Py_BuildValue("s", self->rrclass->toText().c_str());
+}
+
+static PyObject*
+RRClass_str(PyObject* self)
+{
+    // Simply call the to_text method we already defined
+    return PyObject_CallMethod(self, (char*)"to_text", (char*)"");
+}
+
+static PyObject*
+RRClass_toWire(s_RRClass* self, PyObject* args)
+{
+    PyObject* bytes;
+    s_MessageRenderer* mr;
+    
+    if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+        PyObject* bytes_o = bytes;
+        
+        OutputBuffer buffer(2);
+        self->rrclass->toWire(buffer);
+        PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
+        PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+        // We need to release the object we temporarily created here
+        // to prevent memory leak
+        Py_DECREF(n);
+        return result;
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+        self->rrclass->toWire(*mr->messagerenderer);
+        // If we return NULL it is seen as an error, so use this for
+        // None returns
+        Py_RETURN_NONE;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "toWire argument must be a sequence object or a MessageRenderer");
+    return NULL;
+}
+
+static PyObject*
+RRClass_getCode(s_RRClass* self)
+{
+    return Py_BuildValue("I", self->rrclass->getCode());
+}
+
+static PyObject* 
+RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op)
+{
+    bool c;
+
+    switch (op) {
+    case Py_LT:
+        c = *self->rrclass < *other->rrclass;
+        break;
+    case Py_LE:
+        c = *self->rrclass < *other->rrclass ||
+            *self->rrclass == *other->rrclass;
+        break;
+    case Py_EQ:
+        c = self->rrclass->equals(*other->rrclass);
+        break;
+    case Py_NE:
+        c = self->rrclass->nequals(*other->rrclass);
+        break;
+    case Py_GT:
+        c = *other->rrclass < *self->rrclass;
+        break;
+    case Py_GE:
+        c = *other->rrclass < *self->rrclass ||
+            *self->rrclass == *other->rrclass;
+        break;
+    default:
+        assert(0);              // XXX: should trigger an exception
+    }
+    if (c)
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+// end of RRClass
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_RRClass(PyObject* mod)
+{
+    // Add the exceptions to the module
+    po_InvalidRRClass = PyErr_NewException("libdns_python.InvalidRRClass", NULL, NULL);
+    Py_INCREF(po_InvalidRRClass);
+    PyModule_AddObject(mod, "InvalidRRClass", po_InvalidRRClass);
+    po_IncompleteRRClass = PyErr_NewException("libdns_python.IncompleteRRClass", NULL, NULL);
+    Py_INCREF(po_IncompleteRRClass);
+    PyModule_AddObject(mod, "IncompleteRRClass", po_IncompleteRRClass);
+
+    // 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(&rrclass_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&rrclass_type);
+    PyModule_AddObject(mod, "RRClass",
+                       (PyObject*) &rrclass_type);
+    
+    return true;
+}

+ 363 - 0
src/lib/dns/python/rrset_python.cc

@@ -0,0 +1,363 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <dns/rrset.h>
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the module init at the
+// end
+//
+static PyObject* po_EmptyRRset;
+
+// This one's for our 'general' exception
+// TODO: does this need an according general class?
+// should we replace it with some more direct base exception?
+
+//
+// Declaration of enums
+// Initialization and addition of these go in the module init at the
+// end
+//
+
+//
+// Declaration of class constants
+// Initialization and addition of these go in the module init at the
+// end
+//
+
+//
+// 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
+using namespace isc::dns;
+
+// RRset
+typedef struct {
+    PyObject_HEAD
+    RRset* rrset;
+} s_RRset;
+
+static int RRset_init(s_RRset* self, PyObject* args);
+static void RRset_destroy(s_RRset* self);
+
+static PyObject* RRset_getRdataCount(s_RRset* self);
+static PyObject* RRset_getName(s_RRset* self);
+static PyObject* RRset_getClass(s_RRset* self);
+static PyObject* RRset_getType(s_RRset* self);
+static PyObject* RRset_getTTL(s_RRset* self);
+static PyObject* RRset_setName(s_RRset* self, PyObject* args);
+static PyObject* RRset_setTTL(s_RRset* self, PyObject* args);
+static PyObject* RRset_toText(s_RRset* self);
+static PyObject* RRset_toWire(s_RRset* self, PyObject* args);
+static PyObject* RRset_addRdata(s_RRset* self, PyObject* args);
+// TODO: iterator
+
+static PyMethodDef RRset_methods[] = {
+    { "get_rdata_count", (PyCFunction)RRset_getRdataCount, METH_NOARGS, "Return the number of rdata fields" },
+    { "get_name", (PyCFunction)RRset_getName, METH_NOARGS, "Return" },
+    { "get_class", (PyCFunction)RRset_getClass, METH_NOARGS, "Return" },
+    { "get_type", (PyCFunction)RRset_getType, METH_NOARGS, "Return" },
+    { "get_ttl", (PyCFunction)RRset_getTTL, METH_NOARGS, "Return" },
+    { "set_name", (PyCFunction)RRset_setName, METH_VARARGS, "Return" },
+    { "set_ttl", (PyCFunction)RRset_setTTL, METH_VARARGS, "Return" },
+    { "to_text", (PyCFunction)RRset_toText, METH_NOARGS, "Return" },
+    { "to_wire", (PyCFunction)RRset_toWire, METH_VARARGS, "Return" },
+    { "add_rdata", (PyCFunction)RRset_addRdata, METH_VARARGS, "Return" },
+    { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject rrset_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.RRset",
+    sizeof(s_RRset),                       /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)RRset_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 */
+    "C++ Name Object",  /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    NULL,                               /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    RRset_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 */
+    (initproc)RRset_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+static int
+RRset_init(s_RRset* self UNUSED_PARAM, PyObject* args UNUSED_PARAM)
+{
+    s_Name* name;
+    s_RRClass* rrclass;
+    s_RRType* rrtype;
+    s_RRTTL* rrttl;
+
+    if (PyArg_ParseTuple(args, "O!O!O!O!", &name_type, &name,
+                                           &rrclass_type, &rrclass,
+                                           &rrtype_type, &rrtype,
+                                           &rrttl_type, &rrttl
+       )) {
+        self->rrset = new RRset(*name->name, *rrclass->rrclass,
+                                *rrtype->rrtype, *rrttl->rrttl);
+        return 0;
+    }
+
+    self->rrset = NULL;
+    return -1;
+}
+
+static void
+RRset_destroy(s_RRset* self)
+{
+    if (self->rrset != NULL)
+        delete self->rrset;
+    self->rrset = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+RRset_getRdataCount(s_RRset* self)
+{
+    return Py_BuildValue("I", self->rrset->getRdataCount());
+}
+
+static PyObject*
+RRset_getName(s_RRset* self)
+{
+    s_Name* name;
+
+    // is this the best way to do this?
+    name = (s_Name*)name_type.tp_alloc(&name_type, 0);
+    if (name != NULL) {
+        name->name = new Name(self->rrset->getName());
+        if (name->name == NULL)
+          {
+            Py_DECREF(name);
+            return NULL;
+          }
+    }
+
+    return (PyObject*)name;
+}
+
+static PyObject*
+RRset_getClass(s_RRset* self)
+{
+    s_RRClass* rrclass;
+
+    rrclass = (s_RRClass*)rrclass_type.tp_alloc(&rrclass_type, 0);
+    if (rrclass != NULL) {
+        rrclass->rrclass = new RRClass(self->rrset->getClass());
+        if (rrclass->rrclass == NULL)
+          {
+            Py_DECREF(rrclass);
+            return NULL;
+          }
+    }
+
+    return (PyObject*)rrclass;
+}
+
+static PyObject*
+RRset_getType(s_RRset* self)
+{
+    s_RRType* rrtype;
+
+    rrtype = (s_RRType*)rrtype_type.tp_alloc(&rrtype_type, 0);
+    if (rrtype != NULL) {
+        rrtype->rrtype = new RRType(self->rrset->getType());
+        if (rrtype->rrtype == NULL)
+          {
+            Py_DECREF(rrtype);
+            return NULL;
+          }
+    }
+
+    return (PyObject*)rrtype;
+}
+
+static PyObject*
+RRset_getTTL(s_RRset* self)
+{
+    s_RRTTL* rrttl;
+
+    rrttl = (s_RRTTL*)rrttl_type.tp_alloc(&rrttl_type, 0);
+    if (rrttl != NULL) {
+        rrttl->rrttl = new RRTTL(self->rrset->getTTL());
+        if (rrttl->rrttl == NULL)
+          {
+            Py_DECREF(rrttl);
+            return NULL;
+          }
+    }
+
+    return (PyObject*)rrttl;
+}
+
+static PyObject*
+RRset_setName(s_RRset* self, PyObject* args)
+{
+    s_Name* name;
+    if (!PyArg_ParseTuple(args, "O!", &name_type, &name)) {
+        return NULL;
+    }
+    self->rrset->setName(*name->name);
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+RRset_setTTL(s_RRset* self, PyObject* args)
+{
+    s_RRTTL* rrttl;
+    if (!PyArg_ParseTuple(args, "O!", &rrttl_type, &rrttl)) {
+        return NULL;
+    }
+    self->rrset->setTTL(*rrttl->rrttl);
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+RRset_toText(s_RRset* self)
+{
+    try {
+        return Py_BuildValue("s", self->rrset->toText().c_str());
+    } catch (EmptyRRset ers) {
+        PyErr_SetString(po_EmptyRRset, ers.what());
+        return NULL;
+    }
+}
+
+static PyObject*
+RRset_toWire(s_RRset* self, PyObject* args)
+{
+    PyObject* bytes;
+    s_MessageRenderer* mr;
+
+    try {
+        if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+            PyObject* bytes_o = bytes;
+            
+            OutputBuffer buffer(4096);
+            self->rrset->toWire(buffer);
+            PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
+            PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+            // We need to release the object we temporarily created here
+            // to prevent memory leak
+            Py_DECREF(n);
+            return result;
+        } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+            self->rrset->toWire(*mr->messagerenderer);
+            // If we return NULL it is seen as an error, so use this for
+            // None returns
+            Py_RETURN_NONE;
+        }
+    } catch (EmptyRRset ers) {
+        PyErr_Clear();
+        PyErr_SetString(po_EmptyRRset, ers.what());
+        return NULL;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "toWire argument must be a sequence object or a MessageRenderer");
+    return NULL;
+}
+
+static PyObject*
+RRset_addRdata(s_RRset* self, PyObject* args)
+{
+    s_Rdata* rdata;
+    if (!PyArg_ParseTuple(args, "O!", &rdata_type, &rdata)) {
+        return NULL;
+    }
+    try {
+        self->rrset->addRdata(*rdata->rdata);
+        Py_RETURN_NONE;
+    } catch (std::bad_cast) {
+        PyErr_Clear();
+        PyErr_SetString(PyExc_TypeError,
+                        "Rdata type to add must match type of RRset");
+        return NULL;
+    }
+}
+// end of RRset
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_RRset(PyObject* mod)
+{
+    // Add the exceptions to the module
+    po_EmptyRRset = PyErr_NewException("libdns_python.EmptyRRset", NULL, NULL);
+    Py_INCREF(po_EmptyRRset);
+    PyModule_AddObject(mod, "EmptyRRset", po_EmptyRRset);
+
+    // Add the enums to the module
+
+    // Add the constants to the module
+
+    // Add the classes to the module
+    // We initialize the static description object with PyType_Ready(),
+    // then add it to the module
+
+    // NameComparisonResult
+    if (PyType_Ready(&rrset_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&rrset_type);
+    PyModule_AddObject(mod, "RRset",
+                       (PyObject*) &rrset_type);
+    
+    return true;
+}
+

+ 302 - 0
src/lib/dns/python/rrttl_python.cc

@@ -0,0 +1,302 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <dns/rrttl.h>
+using namespace isc::dns;
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function at the end of this file
+//
+static PyObject* po_InvalidRRTTL;
+static PyObject* po_IncompleteRRTTL;
+
+//
+// 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
+
+//
+// RRTTL
+//
+
+// The s_* Class simply coverst one instantiation of the object
+typedef struct {
+    PyObject_HEAD
+    RRTTL* rrttl;
+} s_RRTTL;
+
+//
+// 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
+static int RRTTL_init(s_RRTTL* self, PyObject* args);
+static void RRTTL_destroy(s_RRTTL* self);
+
+// These are the functions we export
+static PyObject* RRTTL_toText(s_RRTTL* self);
+// This is a second version of toText, we need one where the argument
+// is a PyObject*, for the str() function in python.
+static PyObject* RRTTL_str(PyObject* self);
+static PyObject* RRTTL_toWire(s_RRTTL* self, PyObject* args);
+static PyObject* RRTTL_getValue(s_RRTTL* self);
+static PyObject* RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op);
+
+// 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
+static PyMethodDef RRTTL_methods[] = {
+    { "to_text", (PyCFunction)RRTTL_toText, METH_NOARGS, "Return the string representation" },
+    { "to_wire", (PyCFunction)RRTTL_toWire, METH_VARARGS, "to wire format" },
+    { "get_value", (PyCFunction)RRTTL_getValue, METH_NOARGS, "Return the TTL as an integer" },
+    { NULL, NULL, 0, NULL }
+};
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_RRTTL
+// Most of the functions are not actually implemented and NULL here.
+static PyTypeObject rrttl_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.RRTTL",
+    sizeof(s_RRTTL),                  /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)RRTTL_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 */
+    RRTTL_str,                               /* tp_str */
+    NULL,                               /* tp_getattro */
+    NULL,                               /* tp_setattro */
+    NULL,                               /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    "C++ RRTTL Object",               /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    (richcmpfunc)RRTTL_richcmp,       /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    RRTTL_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 */
+    (initproc)RRTTL_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+static int
+RRTTL_init(s_RRTTL* self, PyObject* args)
+{
+    const char* s;
+    unsigned long i;
+    PyObject* bytes = NULL;
+    // The constructor argument can be a string ("IN"), an integer (1),
+    // or a sequence of numbers between 0 and 255 (wire code)
+
+    // Note that PyArg_ParseType can set PyError, and we need to clear
+    // that if we try several like here. Otherwise the *next* python
+    // call will suddenly appear to throw an exception.
+    // (the way to do exceptions is to set PyErr and return -1)
+    try {
+        if (PyArg_ParseTuple(args, "s", &s)) {
+            self->rrttl = new RRTTL(s);
+            return 0;
+        } else if (PyArg_ParseTuple(args, "I", &i)) {
+            PyErr_Clear();
+            self->rrttl = new RRTTL(i);
+            return 0;
+        } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+            uint8_t data[2];
+            int result = readDataFromSequence(data, 2, bytes);
+            if (result != 0) {
+                return result;
+            }
+            InputBuffer ib(data, 2);
+            self->rrttl = new RRTTL(ib);
+            PyErr_Clear();
+            return 0;
+        }
+    } catch (IncompleteRRTTL icc) {
+        // Ok so one of our functions has thrown a C++ exception.
+        // We need to translate that to a Python Exception
+        // First clear any existing error that was set
+        PyErr_Clear();
+        // Now set our own exception
+        PyErr_SetString(po_InvalidRRTTL, icc.what());
+        // And return negative
+        return -1;
+    } catch (InvalidRRTTL ic) {
+        PyErr_Clear();
+        PyErr_SetString(po_InvalidRRTTL, ic.what());
+        return -1;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "no valid type in constructor argument");
+    return -1;
+}
+
+static void
+RRTTL_destroy(s_RRTTL* self)
+{
+    if (self->rrttl != NULL)
+        delete self->rrttl;
+    self->rrttl = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+RRTTL_toText(s_RRTTL* self)
+{
+    // Py_BuildValue makes python objects from native data
+    return Py_BuildValue("s", self->rrttl->toText().c_str());
+}
+
+static PyObject*
+RRTTL_str(PyObject* self)
+{
+    // Simply call the to_text method we already defined
+    return PyObject_CallMethod(self, (char*)"to_text", (char*)"");
+}
+
+static PyObject*
+RRTTL_toWire(s_RRTTL* self, PyObject* args)
+{
+    PyObject* bytes;
+    s_MessageRenderer* mr;
+    
+    if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+        PyObject* bytes_o = bytes;
+        
+        OutputBuffer buffer(2);
+        self->rrttl->toWire(buffer);
+        PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
+        PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+        // We need to release the object we temporarily created here
+        // to prevent memory leak
+        Py_DECREF(n);
+        return result;
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+        self->rrttl->toWire(*mr->messagerenderer);
+        // If we return NULL it is seen as an error, so use this for
+        // None returns
+        Py_RETURN_NONE;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "toWire argument must be a sequence object or a MessageRenderer");
+    return NULL;
+}
+
+static PyObject*
+RRTTL_getValue(s_RRTTL* self)
+{
+    return Py_BuildValue("I", self->rrttl->getValue());
+}
+
+static PyObject* 
+RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op)
+{
+    bool c;
+
+    switch (op) {
+    case Py_LT:
+        c = *self->rrttl < *other->rrttl;
+        break;
+    case Py_LE:
+        c = *self->rrttl < *other->rrttl ||
+            *self->rrttl == *other->rrttl;
+        break;
+    case Py_EQ:
+        c = self->rrttl->equals(*other->rrttl);
+        break;
+    case Py_NE:
+        c = self->rrttl->nequals(*other->rrttl);
+        break;
+    case Py_GT:
+        c = *other->rrttl < *self->rrttl;
+        break;
+    case Py_GE:
+        c = *other->rrttl < *self->rrttl ||
+            *self->rrttl == *other->rrttl;
+        break;
+    default:
+        assert(0);              // XXX: should trigger an exception
+    }
+    if (c)
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+// end of RRTTL
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_RRTTL(PyObject* mod)
+{
+    // Add the exceptions to the module
+    po_InvalidRRTTL = PyErr_NewException("libdns_python.InvalidRRTTL", NULL, NULL);
+    Py_INCREF(po_InvalidRRTTL);
+    PyModule_AddObject(mod, "InvalidRRTTL", po_InvalidRRTTL);
+    po_IncompleteRRTTL = PyErr_NewException("libdns_python.IncompleteRRTTL", NULL, NULL);
+    Py_INCREF(po_IncompleteRRTTL);
+    PyModule_AddObject(mod, "IncompleteRRTTL", po_IncompleteRRTTL);
+
+    // 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(&rrttl_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&rrttl_type);
+    PyModule_AddObject(mod, "RRTTL",
+                       (PyObject*) &rrttl_type);
+    
+    return true;
+}

+ 307 - 0
src/lib/dns/python/rrtype_python.cc

@@ -0,0 +1,307 @@
+// Copyright (C) 2009  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.
+
+// $Id$
+
+#include <dns/rrtype.h>
+using namespace isc::dns;
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function at the end of this file
+//
+static PyObject* po_InvalidRRType;
+static PyObject* po_IncompleteRRType;
+
+//
+// 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
+
+//
+// RRType
+//
+
+// The s_* Class simply coverst one instantiation of the object
+typedef struct {
+    PyObject_HEAD
+    RRType* rrtype;
+} s_RRType;
+
+//
+// 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
+static int RRType_init(s_RRType* self, PyObject* args);
+static void RRType_destroy(s_RRType* self);
+
+// These are the functions we export
+static PyObject* RRType_toText(s_RRType* self);
+// This is a second version of toText, we need one where the argument
+// is a PyObject*, for the str() function in python.
+static PyObject* RRType_str(PyObject* self);
+static PyObject* RRType_toWire(s_RRType* self, PyObject* args);
+static PyObject* RRType_getCode(s_RRType* self);
+static PyObject* RRType_richcmp(s_RRType* self, s_RRType* other, int op);
+//TODO: do we also want specific equals? (and perhaps not even richcmp?)
+
+// 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
+static PyMethodDef RRType_methods[] = {
+    { "to_text", (PyCFunction)RRType_toText, METH_NOARGS, "Return the string representation" },
+    { "to_wire", (PyCFunction)RRType_toWire, METH_VARARGS, "to wire format" },
+    { "get_code", (PyCFunction)RRType_getCode, METH_NOARGS, "Return the class code as an integer" },
+    { NULL, NULL, 0, NULL }
+};
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_RRType
+// Most of the functions are not actually implemented and NULL here.
+static PyTypeObject rrtype_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "libdns_python.RRType",
+    sizeof(s_RRType),                  /* tp_basicsize */
+    0,                                  /* tp_itemsize */
+    (destructor)RRType_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 */
+    RRType_str,                               /* tp_str */
+    NULL,                               /* tp_getattro */
+    NULL,                               /* tp_setattro */
+    NULL,                               /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+    "C++ RRType Object",               /* tp_doc */
+    NULL,                               /* tp_traverse */
+    NULL,                               /* tp_clear */
+    (richcmpfunc)RRType_richcmp,       /* tp_richcompare */
+    0,                                  /* tp_weaklistoffset */
+    NULL,                               /* tp_iter */
+    NULL,                               /* tp_iternext */
+    RRType_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 */
+    (initproc)RRType_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 */
+    // Note: not sure if the following are correct.  Added them just to
+    // make the compiler happy.
+    NULL,                               /* tp_del */
+    0                                   /* tp_version_tag */
+};
+
+static int
+RRType_init(s_RRType* self, PyObject* args)
+{
+    const char* s;
+    unsigned int i;
+    PyObject* bytes = NULL;
+    // The constructor argument can be a string ("IN"), an integer (1),
+    // or a sequence of numbers between 0 and 255 (wire code)
+
+    // Note that PyArg_ParseType can set PyError, and we need to clear
+    // that if we try several like here. Otherwise the *next* python
+    // call will suddenly appear to throw an exception.
+    // (the way to do exceptions is to set PyErr and return -1)
+    try {
+        if (PyArg_ParseTuple(args, "s", &s)) {
+            self->rrtype = new RRType(s);
+            return 0;
+        } else if (PyArg_ParseTuple(args, "I", &i)) {
+            PyErr_Clear();
+            if (i > 65535) {
+                PyErr_SetString(po_InvalidRRType, "Class number too high");
+                return -1;
+            }
+            self->rrtype = new RRType(i);
+            return 0;
+        } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+            uint8_t data[2];
+            int result = readDataFromSequence(data, 2, bytes);
+            if (result != 0) {
+                return result;
+            }
+            InputBuffer ib(data, 2);
+            self->rrtype = new RRType(ib);
+            PyErr_Clear();
+            return 0;
+        }
+    } catch (IncompleteRRType icc) {
+        // Ok so one of our functions has thrown a C++ exception.
+        // We need to translate that to a Python Exception
+        // First clear any existing error that was set
+        PyErr_Clear();
+        // Now set our own exception
+        PyErr_SetString(po_InvalidRRType, icc.what());
+        // And return negative
+        return -1;
+    } catch (InvalidRRType ic) {
+        PyErr_Clear();
+        PyErr_SetString(po_InvalidRRType, ic.what());
+        return -1;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "no valid type in constructor argument");
+    return -1;
+}
+
+static void
+RRType_destroy(s_RRType* self)
+{
+    if (self->rrtype != NULL)
+        delete self->rrtype;
+    self->rrtype = NULL;
+    Py_TYPE(self)->tp_free(self);
+}
+
+static PyObject*
+RRType_toText(s_RRType* self)
+{
+    // Py_BuildValue makes python objects from native data
+    return Py_BuildValue("s", self->rrtype->toText().c_str());
+}
+
+static PyObject*
+RRType_str(PyObject* self)
+{
+    // Simply call the to_text method we already defined
+    return PyObject_CallMethod(self, (char*)"to_text", (char*)"");
+}
+
+static PyObject*
+RRType_toWire(s_RRType* self, PyObject* args)
+{
+    PyObject* bytes;
+    s_MessageRenderer* mr;
+    
+    if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+        PyObject* bytes_o = bytes;
+        
+        OutputBuffer buffer(2);
+        self->rrtype->toWire(buffer);
+        PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
+        PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+        // We need to release the object we temporarily created here
+        // to prevent memory leak
+        Py_DECREF(n);
+        return result;
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
+        self->rrtype->toWire(*mr->messagerenderer);
+        // If we return NULL it is seen as an error, so use this for
+        // None returns
+        Py_RETURN_NONE;
+    }
+    PyErr_Clear();
+    PyErr_SetString(PyExc_TypeError,
+                    "toWire argument must be a sequence object or a MessageRenderer");
+    return NULL;
+}
+
+static PyObject*
+RRType_getCode(s_RRType* self)
+{
+    return Py_BuildValue("I", self->rrtype->getCode());
+}
+
+static PyObject* 
+RRType_richcmp(s_RRType* self, s_RRType* other, int op)
+{
+    bool c;
+
+    switch (op) {
+    case Py_LT:
+        c = *self->rrtype < *other->rrtype;
+        break;
+    case Py_LE:
+        c = *self->rrtype < *other->rrtype ||
+            *self->rrtype == *other->rrtype;
+        break;
+    case Py_EQ:
+        c = self->rrtype->equals(*other->rrtype);
+        break;
+    case Py_NE:
+        c = self->rrtype->nequals(*other->rrtype);
+        break;
+    case Py_GT:
+        c = *other->rrtype < *self->rrtype;
+        break;
+    case Py_GE:
+        c = *other->rrtype < *self->rrtype ||
+            *self->rrtype == *other->rrtype;
+        break;
+    default:
+        assert(0);              // XXX: should trigger an exception
+    }
+    if (c)
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+// end of RRType
+
+
+// Module Initialization, all statics are initialized here
+bool
+initModulePart_RRType(PyObject* mod)
+{
+    // Add the exceptions to the module
+    po_InvalidRRType = PyErr_NewException("libdns_python.InvalidRRType", NULL, NULL);
+    Py_INCREF(po_InvalidRRType);
+    PyModule_AddObject(mod, "InvalidRRType", po_InvalidRRType);
+    po_IncompleteRRType = PyErr_NewException("libdns_python.IncompleteRRType", NULL, NULL);
+    Py_INCREF(po_IncompleteRRType);
+    PyModule_AddObject(mod, "IncompleteRRType", po_IncompleteRRType);
+
+    // 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(&rrtype_type) < 0) {
+        return false;
+    }
+    Py_INCREF(&rrtype_type);
+    PyModule_AddObject(mod, "RRType",
+                       (PyObject*) &rrtype_type);
+    
+    return true;
+}

+ 14 - 0
src/lib/dns/python/tests/libdns_python_test.in

@@ -0,0 +1,14 @@
+#! /bin/sh
+
+PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@}
+export PYTHON_EXEC
+
+CONFIG_PATH=@abs_top_srcdir@/src/lib/dns/python/tests
+
+PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_srcdir@/src/lib/dns/python/.libs
+export PYTHONPATH
+
+cd ${BIND10_PATH}
+${PYTHON_EXEC} -O ${CONFIG_PATH}/rrtype_python_test.py $*
+
+${PYTHON_EXEC} -O ${CONFIG_PATH}/rrset_python_test.py $*

+ 97 - 0
src/lib/dns/python/tests/rrset_python_test.py

@@ -0,0 +1,97 @@
+# Copyright (C) 2009  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.
+
+#
+# Tests for the rrtype part of the libdns_python module
+#
+
+import unittest
+import os
+from libdns_python import *
+
+class TestModuleSpec(unittest.TestCase):
+    
+    def setUp(self):
+        self.test_name = Name("test.example.com")
+        self.test_domain = Name("example.com")
+        self.test_nsname = Name("ns.example.com")
+        self.rrset_a = RRset(self.test_name, RRClass("IN"), RRType("A"), RRTTL(3600))
+        self.rrset_a_empty = RRset(self.test_name, RRClass("IN"), RRType("A"), RRTTL(3600))
+        self.rrset_ns = RRset(self.test_domain, RRClass("IN"), RRType("NS"), RRTTL(86400))
+        self.rrset_ch_txt = RRset(self.test_domain, RRClass("CH"), RRType("TXT"), RRTTL(0))
+        self.MAX_RDATA_COUNT = 100
+        self.rrset_a.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1"));
+        self.rrset_a.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.2"));
+
+    def test_get_rdata_count(self):
+        for i in range(0, self.MAX_RDATA_COUNT):
+            self.assertEqual(i, self.rrset_a_empty.get_rdata_count())
+            self.rrset_a_empty.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1"))
+
+    def test_get_name(self):
+        self.assertEqual(self.test_name, self.rrset_a.get_name())
+        self.assertEqual(self.test_domain, self.rrset_ns.get_name())
+
+    def test_get_class(self):
+        self.assertEqual(RRClass("IN"), self.rrset_a.get_class());
+        self.assertEqual(RRClass("CH"), self.rrset_ch_txt.get_class());
+
+    def test_get_type(self):
+        self.assertEqual(RRType("A"), self.rrset_a.get_type());
+        self.assertEqual(RRType("NS"), self.rrset_ns.get_type());
+        self.assertEqual(RRType("TXT"), self.rrset_ch_txt.get_type());
+
+    def test_get_ttl(self):
+        self.assertEqual(RRTTL(3600), self.rrset_a.get_ttl());
+        self.assertEqual(RRTTL(86400), self.rrset_ns.get_ttl());
+        self.assertEqual(RRTTL(0), self.rrset_ch_txt.get_ttl());
+
+    def test_set_ttl(self):
+        self.rrset_a.set_ttl(RRTTL(86400));
+        self.assertEqual(RRTTL(86400), self.rrset_a.get_ttl());
+        self.rrset_a.set_ttl(RRTTL(0));
+        self.assertEqual(RRTTL(0), self.rrset_a.get_ttl());
+
+    def test_set_name(self):
+        self.rrset_a.set_name(self.test_nsname);
+        self.assertEqual(self.test_nsname, self.rrset_a.get_name());
+
+    def test_add_rdata(self):
+        # no iterator to read out yet (TODO: add addition test once implemented)
+
+        self.assertRaises(TypeError, self.rrset_a.add_rdata, Rdata(RRType("NS"), RRClass("IN"), "test.name"))
+        pass
+
+    def test_to_text(self):
+        self.assertEqual("test.example.com. 3600 IN A 192.0.2.1\n"
+                         "test.example.com. 3600 IN A 192.0.2.2\n",
+                         self.rrset_a.to_text());
+
+    def test_to_wire_buffer(self):
+        exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02')
+        buffer = bytearray()
+        self.rrset_a.to_wire(buffer)
+        self.assertEqual(exp_buffer, buffer)
+
+        self.assertRaises(EmptyRRset, self.rrset_a_empty.to_wire, buffer);
+
+    def test_to_wire_renderer(self):
+        exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\xc0\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02')
+        mr = MessageRenderer()
+        self.rrset_a.to_wire(mr)
+        self.assertEqual(exp_buffer, mr.get_data())
+        
+if __name__ == '__main__':
+    unittest.main()

+ 89 - 0
src/lib/dns/python/tests/rrtype_python_test.py

@@ -0,0 +1,89 @@
+# Copyright (C) 2009  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.
+
+#
+# Tests for the rrtype part of the libdns_python module
+#
+
+import unittest
+import os
+from libdns_python import *
+
+class TestModuleSpec(unittest.TestCase):
+    
+    rrtype_1 = RRType(1)
+    rrtype_0x80 = RRType(0x80);
+    rrtype_0x800 = RRType(0x800);
+    rrtype_0x8000 = RRType(0x8000);
+    rrtype_max = RRType(0xffff);
+    wiredata = bytearray(b'\x00\x01\x00\x80\x08\x00\x80\x00\xff\xff');
+
+    def test_from_text(self):
+        self.assertEqual("A", RRType("A").to_text())
+        self.assertEqual("NS", RRType("NS").to_text());
+    
+        self.assertEqual("TYPE65535", RRType("TYPE65535").to_text());
+    
+        self.assertEqual(53, RRType("TYPE00053").get_code());
+
+        self.assertRaises(InvalidRRType, RRType, "TYPE000053");
+    
+        self.assertRaises(InvalidRRType, RRType, "TYPE");
+        self.assertRaises(InvalidRRType, RRType, "TYPE-1");
+        self.assertRaises(InvalidRRType, RRType, "TYPExxx");
+        self.assertRaises(InvalidRRType, RRType, "TYPE65536");
+        self.assertRaises(InvalidRRType, RRType, "TYPE6500x");
+        self.assertRaises(InvalidRRType, RRType, "TYPE65000 ");
+
+    def test_case_construct(self):
+        self.assertEqual("A", RRType("a").to_text());
+        self.assertEqual("NS", RRType("ns").to_text());
+        self.assertEqual("TYPE65535", RRType("type65535").to_text());
+
+    def test_to_text(self):
+        self.assertEqual("A", RRType(1).to_text());
+        self.assertEqual("TYPE65000", RRType(65000).to_text());
+
+    def test_to_wire_buffer(self):
+        obuffer = bytearray()
+        self.rrtype_1.to_wire(obuffer);
+        self.rrtype_0x80.to_wire(obuffer);
+        self.rrtype_0x800.to_wire(obuffer);
+        self.rrtype_0x8000.to_wire(obuffer);
+        self.rrtype_max.to_wire(obuffer);
+
+        self.assertEqual(self.wiredata, obuffer)
+        
+    def test_to_wire_renderer(self):
+        mr = MessageRenderer()
+        self.rrtype_1.to_wire(mr);
+        self.rrtype_0x80.to_wire(mr);
+        self.rrtype_0x800.to_wire(mr);
+        self.rrtype_0x8000.to_wire(mr);
+        self.rrtype_max.to_wire(mr);
+
+        self.assertEqual(self.wiredata, mr.get_data())
+
+    def test_compare(self):
+        self.assertTrue(RRType(1) == RRType("A"));
+        #self.assertTrue(RRType(1).equals(RRType("A")));
+        self.assertTrue(RRType(0) != RRType("A"));
+        #self.assertTrue(RRType(0).nequals(RRType("A")));
+    
+        self.assertTrue(RRType("A") < RRType("NS"));
+        self.assertTrue(RRType(100) < RRType(65535));
+        
+if __name__ == '__main__':
+    unittest.main()

+ 34 - 0
src/lib/dns/python/tests/test.py

@@ -0,0 +1,34 @@
+#!/usr/bin/python3.1
+
+import libdns_python
+
+#for i in range(0,3):
+#b = bytearray()
+#while True:
+#    c = libdns_python.RRClass("IN")
+#    #print(dir(b))
+#    c.toWire(b)
+#    #print("b:")
+#    print(b)
+#    #print("d:")
+#    #print(d)
+
+#m = libdns_python.MessageRenderer()
+#c1 = libdns_python.RRClass("IN")
+#c2 = libdns_python.RRClass("CH")
+#c3 = libdns_python.RRClass("IN")
+#b2 = bytearray()
+#d.toWire(b2)
+#print(b2)
+n = libdns_python.Name("tjeb.nl")
+t = libdns_python.RRType("A")
+c = libdns_python.RRClass("IN")
+ttl = libdns_python.RRTTL(1234)
+
+#set = libdns_python.RRset(1,2,3,4)
+
+set = libdns_python.RRset(n, c, t, ttl)
+#print(set.toText())
+rd = libdns_python.Rdata(t, c, "123.123.123.123")
+set.add_rdata(rd)
+print(set.to_text())

+ 1 - 0
src/lib/python/isc/__init__.py

@@ -1,3 +1,4 @@
 import isc.auth
 import isc.cc
 import isc.config
+import isc.dns

+ 1 - 0
src/lib/python/isc/dns/__init__.py

@@ -0,0 +1 @@
+from libdns_python_name import *

+ 1 - 0
tools/import_boost.sh

@@ -30,6 +30,7 @@ boost/function
 boost/iterator
 boost/mpl
 boost/preprocessor
+boost/python
 boost/range
 boost/smart_ptr
 boost/type_traits