BIND 10 master, updated. af10f1ef696ee94f817bc389e0e8b6cd08234333 [1245] use forward decl in xxx_python.h where practical

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Sep 20 19:36:40 UTC 2011


The branch, master has been updated
       via  af10f1ef696ee94f817bc389e0e8b6cd08234333 (commit)
       via  3eb0dedb8a5d9835b394484c6112a4b2fcbe9d51 (commit)
       via  2f8c4b3da6060a9b57e944726dd61cb1b2a19906 (commit)
       via  433f29fd44d8dd6c940e49ee2657b769d70781fe (commit)
       via  45ef63790b34ebc2d26081609bb168aefee800dc (commit)
       via  cbf08d56345922d754182b941b84b18bfddabcda (commit)
       via  84a95705e1e8219187e75433baec2fd2fc8ba2fe (commit)
       via  aa5fd84d438cf165c9836fa545d15c33781401af (commit)
       via  fac67afceead36ba7296e194942811d9ed3b437b (commit)
       via  90b740caf4cc5d207dfa2ac98f1c73d9818792e2 (commit)
       via  0ea828cb5c74b0f9a254aeab2c7d31ff214371e5 (commit)
       via  170a0661dfb17014a62cd2eeaaa99e408bc55a14 (commit)
       via  b12f4e55007ee2e8130991f322e782bb31a8a289 (commit)
       via  18083458382473b414a3fc7f57623d2241f487ef (commit)
       via  fbe4ee1f76237fdd586638ce1ded4c6e5bd0bf1d (commit)
       via  9c53309978b4a4bf684b3abbb853876c5413f875 (commit)
       via  8ee5844e8dc3ec7d99a5890bdc85f54afd8886b6 (commit)
       via  c9ad781ebbaebb2e57956ac9eda542eaa88a743b (commit)
       via  4d39f72b87677c194d282a9e93de67dc0adfb4f3 (commit)
       via  ece8bd155e646869b10fd08817ee7cd71c699c61 (commit)
       via  b59f898456b33294d71a333d3f3b4fe9dc81e3dd (commit)
      from  02b2e71bdc1564f4272869bb5676727af809870f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit af10f1ef696ee94f817bc389e0e8b6cd08234333
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 20 16:50:31 2011 +0200

    [1245] use forward decl in xxx_python.h where practical

commit 3eb0dedb8a5d9835b394484c6112a4b2fcbe9d51
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 20 16:34:44 2011 +0200

    [1245] add NULL checks in PyXXX_ToXXX() functions

commit 2f8c4b3da6060a9b57e944726dd61cb1b2a19906
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 20 16:14:58 2011 +0200

    [1245] catch exceptions where createXXXObject() is called
    
    and removed unused createMessageRendererObject function

commit 433f29fd44d8dd6c940e49ee2657b769d70781fe
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Tue Sep 20 00:46:33 2011 -0700

    [1245] adjusted the python wrapper template so it works with the change
    of the assumption on @CPPCLASS at Container constructor (it's now explicit)

commit 45ef63790b34ebc2d26081609bb168aefee800dc
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 20 00:23:37 2011 +0200

    [1245] move initModulePart calls to pydnspp.cc

commit cbf08d56345922d754182b941b84b18bfddabcda
Author: Jelte Jansen <jelte at isc.org>
Date:   Sat Sep 17 00:44:36 2011 +0200

    [1245] remove some unnecessary comments

commit 84a95705e1e8219187e75433baec2fd2fc8ba2fe
Merge: 90b740caf4cc5d207dfa2ac98f1c73d9818792e2 aa5fd84d438cf165c9836fa545d15c33781401af
Author: Jelte Jansen <jelte at isc.org>
Date:   Sat Sep 17 00:28:19 2011 +0200

    Merge branch 'trac1245' of ssh://git.bind10.isc.org/var/bind10/git/bind10 into trac1245

commit aa5fd84d438cf165c9836fa545d15c33781401af
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 22:27:29 2011 +0000

    [1245] remove #include <config.h>

commit fac67afceead36ba7296e194942811d9ed3b437b
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 22:25:00 2011 +0000

    [1245] remove const for sunstudio build

commit 90b740caf4cc5d207dfa2ac98f1c73d9818792e2
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 23:11:34 2011 +0200

    [1245] namespace fix

commit 0ea828cb5c74b0f9a254aeab2c7d31ff214371e5
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 22:52:11 2011 +0200

    [1245] raise exception in _Check() if obj is NULL

commit 170a0661dfb17014a62cd2eeaaa99e408bc55a14
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 22:01:23 2011 +0200

    [1245] Make CPPPyObjectContainer constructor explicit

commit b12f4e55007ee2e8130991f322e782bb31a8a289
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 21:51:54 2011 +0200

    [1245] update makefile and fix createRRsetObject

commit 18083458382473b414a3fc7f57623d2241f487ef
Author: Jelte Jansen <jelte at isc.org>
Date:   Fri Sep 16 01:35:40 2011 +0200

    [1245] move all s_ decls to inside the .cc
    
    Added a lot of conversion functions for that

commit fbe4ee1f76237fdd586638ce1ded4c6e5bd0bf1d
Author: Jelte Jansen <jelte at isc.org>
Date:   Thu Sep 15 21:50:02 2011 +0200

    [1245] rename internal object to cppobj for consistency

commit 9c53309978b4a4bf684b3abbb853876c5413f875
Author: Jelte Jansen <jelte at isc.org>
Date:   Thu Sep 15 21:09:15 2011 +0200

    [1245] remove initModule from headers
    
    and move it to an internal namespace
    move the declaration of the functions to pydnspp.cc

commit 8ee5844e8dc3ec7d99a5890bdc85f54afd8886b6
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Wed Sep 14 21:08:06 2011 -0700

    [1245] editorial cleanups: removed unnecesary 'static'; fixed typo in comments.

commit c9ad781ebbaebb2e57956ac9eda542eaa88a743b
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Wed Sep 14 08:06:14 2011 -0700

    [1245] two small fixes: missing LIBRARY_PATH_PLACEHOLDER in some
    test's Makefile.am (usual MacOS nit); made sure PY_SSIZE_T_CLEAN is
    defined when 'y#' is used with PyArg_ParseTuple.  For the latter, see
    http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers

commit 4d39f72b87677c194d282a9e93de67dc0adfb4f3
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 13 12:25:15 2011 +0200

    [1245] cleanup of some comments in .cc files
    
    A lot of the comments were leftovers from when this was all one big source file, and in individual files the comments were either wrong or superfluous (since the that was commented is self-explanatory with the context now)

commit ece8bd155e646869b10fd08817ee7cd71c699c61
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 13 12:15:38 2011 +0200

    [1245] clean up headers

commit b59f898456b33294d71a333d3f3b4fe9dc81e3dd
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Sep 13 11:08:10 2011 +0200

    [1245] split up headers and make dynamic library
    
    None of the .cc files are now included directly anymore, and the
    main source file for the python module contains only the module definition. All functionality is moved to a dynamic library that is also usable by other wrapper modules.
    
    Also split up the rest of the source files into header and code files, and made them more consistent with the rest.
    
    Added conversion from/to PyObject* for some of the types (the ones I needed so far for trac1179)

-----------------------------------------------------------------------

Summary of changes:
 src/bin/cfgmgr/plugins/tests/Makefile.am           |    2 +-
 src/bin/xfrin/tests/Makefile.am                    |    2 +-
 src/bin/xfrout/tests/Makefile.am                   |    2 +-
 src/lib/dns/python/Makefile.am                     |   52 +-
 src/lib/dns/python/edns_python.cc                  |  262 ++++----
 .../python/{tsig_rdata_python.h => edns_python.h}  |   49 +-
 src/lib/dns/python/message_python.cc               |  465 ++++++--------
 .../python/message_python.h}                       |   26 +-
 src/lib/dns/python/messagerenderer_python.cc       |   94 ++--
 src/lib/dns/python/messagerenderer_python.h        |   37 +-
 src/lib/dns/python/name_python.cc                  |  133 +---
 src/lib/dns/python/name_python.h                   |   45 +-
 src/lib/dns/python/opcode_python.cc                |  231 +++----
 .../{tsig_rdata_python.h => opcode_python.h}       |   49 +-
 src/lib/dns/python/pydnspp.cc                      |  689 +++++++++++++++++++-
 src/lib/dns/python/pydnspp_common.cc               |   36 +
 src/lib/dns/python/pydnspp_common.h                |    2 -
 src/lib/dns/python/pydnspp_towire.h                |    4 +-
 src/lib/dns/python/question_python.cc              |  271 +++++----
 .../{tsigrecord_python.h => question_python.h}     |   45 +-
 src/lib/dns/python/rcode_python.cc                 |  109 ++--
 src/lib/dns/python/rcode_python.h                  |   49 +-
 src/lib/dns/python/rdata_python.cc                 |  289 +++++----
 .../python/{tsig_rdata_python.h => rdata_python.h} |   53 +-
 src/lib/dns/python/rrclass_python.cc               |  303 +++++----
 .../{tsigrecord_python.h => rrclass_python.h}      |   47 +-
 src/lib/dns/python/rrset_python.cc                 |  494 ++++++++------
 src/lib/dns/python/rrset_python.h                  |   78 +++
 src/lib/dns/python/rrttl_python.cc                 |  281 ++++----
 .../python/{tsig_rdata_python.h => rrttl_python.h} |   50 +-
 src/lib/dns/python/rrtype_python.cc                |  348 +++++-----
 .../{tsigrecord_python.h => rrtype_python.h}       |   47 +-
 src/lib/dns/python/tests/Makefile.am               |    2 +-
 src/lib/dns/python/tsig_python.cc                  |  105 +--
 src/lib/dns/python/tsig_python.h                   |   28 +-
 src/lib/dns/python/tsig_rdata_python.cc            |   62 +-
 src/lib/dns/python/tsig_rdata_python.h             |   29 +-
 src/lib/dns/python/tsigerror_python.cc             |  105 +---
 src/lib/dns/python/tsigerror_python.h              |   10 +-
 src/lib/dns/python/tsigkey_python.cc               |  133 ++---
 src/lib/dns/python/tsigkey_python.h                |   52 +-
 src/lib/dns/python/tsigrecord_python.cc            |   82 +--
 src/lib/dns/python/tsigrecord_python.h             |   28 +-
 src/lib/python/isc/acl/tests/Makefile.am           |    2 +-
 src/lib/python/isc/notify/tests/Makefile.am        |    2 +-
 src/lib/util/python/pycppwrapper_util.h            |    2 +-
 src/lib/util/python/wrapper_template.cc            |    4 +-
 src/lib/util/python/wrapper_template.h             |    6 +-
 48 files changed, 2978 insertions(+), 2318 deletions(-)
 copy src/lib/dns/python/{tsig_rdata_python.h => edns_python.h} (54%)
 copy src/lib/{python/isc/acl/dns_requestloader_python.h => dns/python/message_python.h} (69%)
 copy src/lib/dns/python/{tsig_rdata_python.h => opcode_python.h} (53%)
 copy src/lib/dns/python/{tsigrecord_python.h => question_python.h} (51%)
 copy src/lib/dns/python/{tsig_rdata_python.h => rdata_python.h} (50%)
 copy src/lib/dns/python/{tsigrecord_python.h => rrclass_python.h} (51%)
 create mode 100644 src/lib/dns/python/rrset_python.h
 copy src/lib/dns/python/{tsig_rdata_python.h => rrttl_python.h} (52%)
 copy src/lib/dns/python/{tsigrecord_python.h => rrtype_python.h} (51%)

-----------------------------------------------------------------------
diff --git a/src/bin/cfgmgr/plugins/tests/Makefile.am b/src/bin/cfgmgr/plugins/tests/Makefile.am
index 07b7a85..bda775b 100644
--- a/src/bin/cfgmgr/plugins/tests/Makefile.am
+++ b/src/bin/cfgmgr/plugins/tests/Makefile.am
@@ -7,7 +7,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/bin/xfrin/tests/Makefile.am b/src/bin/xfrin/tests/Makefile.am
index 0f485aa..e8319d5 100644
--- a/src/bin/xfrin/tests/Makefile.am
+++ b/src/bin/xfrin/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/bin/xfrout/tests/Makefile.am b/src/bin/xfrout/tests/Makefile.am
index 2f1e2ea..1b99e37 100644
--- a/src/bin/xfrout/tests/Makefile.am
+++ b/src/bin/xfrout/tests/Makefile.am
@@ -6,7 +6,7 @@ noinst_SCRIPTS = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/acl/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/acl/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/dns/python/Makefile.am b/src/lib/dns/python/Makefile.am
index 6c4ef54..4452e40 100644
--- a/src/lib/dns/python/Makefile.am
+++ b/src/lib/dns/python/Makefile.am
@@ -4,40 +4,46 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-pyexec_LTLIBRARIES = pydnspp.la
-pydnspp_la_SOURCES = pydnspp.cc pydnspp_common.cc pydnspp_towire.h
-pydnspp_la_SOURCES += name_python.cc name_python.h
-pydnspp_la_SOURCES += messagerenderer_python.cc messagerenderer_python.h
-pydnspp_la_SOURCES += rcode_python.cc rcode_python.h
-pydnspp_la_SOURCES += tsigkey_python.cc tsigkey_python.h
-pydnspp_la_SOURCES += tsigerror_python.cc tsigerror_python.h
-pydnspp_la_SOURCES += tsig_rdata_python.cc tsig_rdata_python.h
-pydnspp_la_SOURCES += tsigrecord_python.cc tsigrecord_python.h
-pydnspp_la_SOURCES += tsig_python.cc tsig_python.h
+lib_LTLIBRARIES = libpydnspp.la
+libpydnspp_la_SOURCES = pydnspp_common.cc pydnspp_common.h pydnspp_towire.h
+libpydnspp_la_SOURCES += name_python.cc name_python.h
+libpydnspp_la_SOURCES += rrset_python.cc rrset_python.h
+libpydnspp_la_SOURCES += rrclass_python.cc rrclass_python.h
+libpydnspp_la_SOURCES += rrtype_python.cc rrtype_python.h
+libpydnspp_la_SOURCES += rrttl_python.cc rrttl_python.h
+libpydnspp_la_SOURCES += rdata_python.cc rdata_python.h
+libpydnspp_la_SOURCES += messagerenderer_python.cc messagerenderer_python.h
+libpydnspp_la_SOURCES += rcode_python.cc rcode_python.h
+libpydnspp_la_SOURCES += opcode_python.cc opcode_python.h
+libpydnspp_la_SOURCES += question_python.cc question_python.h
+libpydnspp_la_SOURCES += tsigkey_python.cc tsigkey_python.h
+libpydnspp_la_SOURCES += tsigerror_python.cc tsigerror_python.h
+libpydnspp_la_SOURCES += tsig_rdata_python.cc tsig_rdata_python.h
+libpydnspp_la_SOURCES += tsigrecord_python.cc tsigrecord_python.h
+libpydnspp_la_SOURCES += tsig_python.cc tsig_python.h
+libpydnspp_la_SOURCES += edns_python.cc edns_python.h
+libpydnspp_la_SOURCES += message_python.cc message_python.h
+
+libpydnspp_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
+libpydnspp_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
+libpydnspp_la_LDFLAGS = $(PYTHON_LDFLAGS)
+
 
+
+pyexec_LTLIBRARIES = pydnspp.la
+pydnspp_la_SOURCES = pydnspp.cc
 pydnspp_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
 # Note: PYTHON_CXXFLAGS may have some -Wno... workaround, which must be
 # placed after -Wextra defined in AM_CXXFLAGS
 pydnspp_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
 pydnspp_la_LDFLAGS = $(PYTHON_LDFLAGS)
 
-# directly included from source files, so these don't have their own
-# rules
-EXTRA_DIST = pydnspp_common.h
-EXTRA_DIST += edns_python.cc
-EXTRA_DIST += message_python.cc
-EXTRA_DIST += rrclass_python.cc
-EXTRA_DIST += opcode_python.cc
-EXTRA_DIST += rrset_python.cc
-EXTRA_DIST += question_python.cc
-EXTRA_DIST += rrttl_python.cc
-EXTRA_DIST += rdata_python.cc
-EXTRA_DIST += rrtype_python.cc
-EXTRA_DIST += tsigerror_python_inc.cc
+EXTRA_DIST = tsigerror_python_inc.cc
 
 # Python prefers .so, while some OSes (specifically MacOS) use a different
 # suffix for dynamic objects.  -module is necessary to work this around.
 pydnspp_la_LDFLAGS += -module
 pydnspp_la_LIBADD = $(top_builddir)/src/lib/dns/libdns++.la
 pydnspp_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+pydnspp_la_LIBADD += libpydnspp.la
 pydnspp_la_LIBADD += $(PYTHON_LIB)
diff --git a/src/lib/dns/python/edns_python.cc b/src/lib/dns/python/edns_python.cc
index 83c3bfa..8f0f1a4 100644
--- a/src/lib/dns/python/edns_python.cc
+++ b/src/lib/dns/python/edns_python.cc
@@ -12,38 +12,38 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <Python.h>
+
 #include <cassert>
 
 #include <dns/edns.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <util/python/pycppwrapper_util.h>
+
+#include "edns_python.h"
+#include "name_python.h"
+#include "rrclass_python.h"
+#include "rrtype_python.h"
+#include "rrttl_python.h"
+#include "rdata_python.h"
+#include "messagerenderer_python.h"
+#include "pydnspp_common.h"
 
 using namespace isc::dns;
-using namespace isc::util;
 using namespace isc::dns::rdata;
-
-//
-// 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::python;
+using namespace isc::util;
+using namespace isc::util::python;
 
 namespace {
-//
-// EDNS
-//
-
-// The s_* Class simply covers one instantiation of the object
 
 class s_EDNS : public PyObject {
 public:
-    EDNS* edns;
+    EDNS* cppobj;
 };
 
-//
-// We declare the functions here, the definitions are below
-// the type definition of the object, since both can use the other
-//
+typedef CPPPyObjectContainer<s_EDNS, EDNS> EDNSContainer;
 
 // General creation and destruction
 int EDNS_init(s_EDNS* self, PyObject* args);
@@ -103,60 +103,6 @@ PyMethodDef EDNS_methods[] = {
     { NULL, NULL, 0, NULL }
 };
 
-// This defines the complete type for reflection in python and
-// parsing of PyObject* to s_EDNS
-// Most of the functions are not actually implemented and NULL here.
-PyTypeObject edns_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "pydnspp.EDNS",
-    sizeof(s_EDNS),                     // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)EDNS_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
-    EDNS_str,                           // tp_str
-    NULL,                               // tp_getattro
-    NULL,                               // tp_setattro
-    NULL,                               // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "The EDNS class encapsulates DNS extensions "
-    "provided by the EDNSx protocol.",
-    NULL,                               // tp_traverse
-    NULL,                               // tp_clear
-    NULL,                               // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    NULL,                               // tp_iter
-    NULL,                               // tp_iternext
-    EDNS_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)EDNS_init,                // tp_init
-    NULL,                               // tp_alloc
-    PyType_GenericNew,                  // tp_new
-    NULL,                               // tp_free
-    NULL,                               // tp_is_gc
-    NULL,                               // tp_bases
-    NULL,                               // tp_mro
-    NULL,                               // tp_cache
-    NULL,                               // tp_subclasses
-    NULL,                               // tp_weaklist
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
 EDNS*
 createFromRR(const Name& name, const RRClass& rrclass, const RRType& rrtype,
              const RRTTL& rrttl, const Rdata& rdata, uint8_t& extended_rcode)
@@ -179,15 +125,15 @@ createFromRR(const Name& name, const RRClass& rrclass, const RRType& rrtype,
 int
 EDNS_init(s_EDNS* self, PyObject* args) {
     uint8_t version = EDNS::SUPPORTED_VERSION;
-    const s_Name* name;
-    const s_RRClass* rrclass;
-    const s_RRType* rrtype;
-    const s_RRTTL* rrttl;
-    const s_Rdata* rdata;
+    const PyObject* name;
+    const PyObject* rrclass;
+    const PyObject* rrtype;
+    const PyObject* rrttl;
+    const PyObject* rdata;
 
     if (PyArg_ParseTuple(args, "|b", &version)) {
         try {
-            self->edns = new EDNS(version);
+            self->cppobj = new EDNS(version);
         } catch (const isc::InvalidParameter& ex) {
             PyErr_SetString(po_InvalidParameter, ex.what());
             return (-1);
@@ -203,10 +149,12 @@ EDNS_init(s_EDNS* self, PyObject* args) {
         // in this context so that we can share the try-catch logic with
         // EDNS_createFromRR() (see below).
         uint8_t extended_rcode;
-        self->edns = createFromRR(*name->cppobj, *rrclass->rrclass,
-                                  *rrtype->rrtype, *rrttl->rrttl,
-                                  *rdata->rdata, extended_rcode);
-        return (self->edns != NULL ? 0 : -1);
+        self->cppobj = createFromRR(PyName_ToName(name),
+                                    PyRRClass_ToRRClass(rrclass),
+                                    PyRRType_ToRRType(rrtype),
+                                    PyRRTTL_ToRRTTL(rrttl),
+                                    PyRdata_ToRdata(rdata), extended_rcode);
+        return (self->cppobj != NULL ? 0 : -1);
     }
 
     PyErr_Clear();
@@ -217,19 +165,19 @@ EDNS_init(s_EDNS* self, PyObject* args) {
 
 void
 EDNS_destroy(s_EDNS* const self) {
-    delete self->edns;
-    self->edns = NULL;
+    delete self->cppobj;
+    self->cppobj = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
 PyObject*
 EDNS_toText(const s_EDNS* const self) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->edns->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
 PyObject*
-EDNS_str(PyObject* const self) {
+EDNS_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
                                 const_cast<char*>("to_text"),
@@ -240,14 +188,14 @@ PyObject*
 EDNS_toWire(const s_EDNS* const self, PyObject* args) {
     PyObject* bytes;
     uint8_t extended_rcode;
-    s_MessageRenderer* renderer;
+    PyObject* renderer;
 
     if (PyArg_ParseTuple(args, "Ob", &bytes, &extended_rcode) &&
         PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
-        
+
         OutputBuffer buffer(0);
-        self->edns->toWire(buffer, extended_rcode);
+        self->cppobj->toWire(buffer, extended_rcode);
         PyObject* rd_bytes = PyBytes_FromStringAndSize(
             static_cast<const char*>(buffer.getData()), buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, rd_bytes);
@@ -257,8 +205,8 @@ EDNS_toWire(const s_EDNS* const self, PyObject* args) {
         return (result);
     } else if (PyArg_ParseTuple(args, "O!b", &messagerenderer_type,
                                 &renderer, &extended_rcode)) {
-        const unsigned int n = self->edns->toWire(*renderer->messagerenderer,
-                                                  extended_rcode);
+        const unsigned int n = self->cppobj->toWire(
+            PyMessageRenderer_ToMessageRenderer(renderer), extended_rcode);
 
         return (Py_BuildValue("I", n));
     }
@@ -269,12 +217,12 @@ EDNS_toWire(const s_EDNS* const self, PyObject* args) {
 
 PyObject*
 EDNS_getVersion(const s_EDNS* const self) {
-    return (Py_BuildValue("B", self->edns->getVersion()));
+    return (Py_BuildValue("B", self->cppobj->getVersion()));
 }
 
 PyObject*
 EDNS_getDNSSECAwareness(const s_EDNS* const self) {
-    if (self->edns->getDNSSECAwareness()) {
+    if (self->cppobj->getDNSSECAwareness()) {
         Py_RETURN_TRUE;
     } else {
         Py_RETURN_FALSE;
@@ -287,13 +235,13 @@ EDNS_setDNSSECAwareness(s_EDNS* self, PyObject* args) {
     if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &b)) {
         return (NULL);
     }
-    self->edns->setDNSSECAwareness(b == Py_True);
+    self->cppobj->setDNSSECAwareness(b == Py_True);
     Py_RETURN_NONE;
 }
 
 PyObject*
 EDNS_getUDPSize(const s_EDNS* const self) {
-    return (Py_BuildValue("I", self->edns->getUDPSize()));
+    return (Py_BuildValue("I", self->cppobj->getUDPSize()));
 }
 
 PyObject*
@@ -310,17 +258,17 @@ EDNS_setUDPSize(s_EDNS* self, PyObject* args) {
                         "UDP size is not an unsigned 16-bit integer");
         return (NULL);
     }
-    self->edns->setUDPSize(size);
+    self->cppobj->setUDPSize(size);
     Py_RETURN_NONE;
 }
 
 PyObject*
 EDNS_createFromRR(const s_EDNS* null_self, PyObject* args) {
-    const s_Name* name;
-    const s_RRClass* rrclass;
-    const s_RRType* rrtype;
-    const s_RRTTL* rrttl;
-    const s_Rdata* rdata;
+    const PyObject* name;
+    const PyObject* rrclass;
+    const PyObject* rrtype;
+    const PyObject* rrttl;
+    const PyObject* rdata;
     s_EDNS* edns_obj = NULL;
 
     assert(null_self == NULL);
@@ -334,14 +282,17 @@ EDNS_createFromRR(const s_EDNS* null_self, PyObject* args) {
             return (NULL);
         }
 
-        edns_obj->edns = createFromRR(*name->cppobj, *rrclass->rrclass,
-                                      *rrtype->rrtype, *rrttl->rrttl,
-                                      *rdata->rdata, extended_rcode);
-        if (edns_obj->edns != NULL) {
+        edns_obj->cppobj = createFromRR(PyName_ToName(name),
+                                        PyRRClass_ToRRClass(rrclass),
+                                        PyRRType_ToRRType(rrtype),
+                                        PyRRTTL_ToRRTTL(rrttl),
+                                        PyRdata_ToRdata(rdata),
+                                        extended_rcode);
+        if (edns_obj->cppobj != NULL) {
             PyObject* extrcode_obj = Py_BuildValue("B", extended_rcode);
             return (Py_BuildValue("OO", edns_obj, extrcode_obj));
         }
-        
+
         Py_DECREF(edns_obj);
         return (NULL);
     }
@@ -353,23 +304,90 @@ EDNS_createFromRR(const s_EDNS* null_self, PyObject* args) {
 }
 
 } // end of anonymous namespace
-// end of EDNS
 
-// Module Initialization, all statics are initialized here
+namespace isc {
+namespace dns {
+namespace python {
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_EDNS
+// Most of the functions are not actually implemented and NULL here.
+PyTypeObject edns_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.EDNS",
+    sizeof(s_EDNS),                     // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)EDNS_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
+    EDNS_str,                           // tp_str
+    NULL,                               // tp_getattro
+    NULL,                               // tp_setattro
+    NULL,                               // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "The EDNS class encapsulates DNS extensions "
+    "provided by the EDNSx protocol.",
+    NULL,                               // tp_traverse
+    NULL,                               // tp_clear
+    NULL,                               // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    NULL,                               // tp_iter
+    NULL,                               // tp_iternext
+    EDNS_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)EDNS_init,                // tp_init
+    NULL,                               // tp_alloc
+    PyType_GenericNew,                  // tp_new
+    NULL,                               // tp_free
+    NULL,                               // tp_is_gc
+    NULL,                               // tp_bases
+    NULL,                               // tp_mro
+    NULL,                               // tp_cache
+    NULL,                               // tp_subclasses
+    NULL,                               // tp_weaklist
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+PyObject*
+createEDNSObject(const EDNS& source) {
+    EDNSContainer container(PyObject_New(s_EDNS, &edns_type));
+    container.set(new EDNS(source));
+    return (container.release());
+}
+
 bool
-initModulePart_EDNS(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&edns_type) < 0) {
-        return (false);
+PyEDNS_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
-    Py_INCREF(&edns_type);
-    void* p = &edns_type;
-    PyModule_AddObject(mod, "EDNS", static_cast<PyObject*>(p));
-
-    addClassVariable(edns_type, "SUPPORTED_VERSION",
-                     Py_BuildValue("B", EDNS::SUPPORTED_VERSION));
+    return (PyObject_TypeCheck(obj, &edns_type));
+}
 
-    return (true);
+const EDNS&
+PyEDNS_ToEDNS(const PyObject* edns_obj) {
+    if (edns_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in EDNS PyObject conversion");
+    }
+    const s_EDNS* edns = static_cast<const s_EDNS*>(edns_obj);
+    return (*edns->cppobj);
 }
+
+} // end namespace python
+} // end namespace dns
+} // end namespace isc
diff --git a/src/lib/dns/python/edns_python.h b/src/lib/dns/python/edns_python.h
new file mode 100644
index 0000000..30d92ab
--- /dev/null
+++ b/src/lib/dns/python/edns_python.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_EDNS_H
+#define __PYTHON_EDNS_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class EDNS;
+
+namespace python {
+
+extern PyTypeObject edns_type;
+
+/// This is a simple shortcut to create a python EDNS object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createEDNSObject(const EDNS& source);
+
+/// \brief Checks if the given python object is a EDNS object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type EDNS, false otherwise
+bool PyEDNS_Check(PyObject* obj);
+
+/// \brief Returns a reference to the EDNS object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type EDNS; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyEDNS_Check()
+///
+/// \note This is not a copy; if the EDNS is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param edns_obj The edns object to convert
+const EDNS& PyEDNS_ToEDNS(const PyObject* edns_obj);
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_EDNS_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc
index 00596f8..b40ab45 100644
--- a/src/lib/dns/python/message_python.cc
+++ b/src/lib/dns/python/message_python.cc
@@ -12,49 +12,39 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
 #include <exceptions/exceptions.h>
 #include <dns/message.h>
 #include <dns/rcode.h>
 #include <dns/tsig.h>
-
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+
+#include "name_python.h"
+#include "question_python.h"
+#include "edns_python.h"
+#include "rcode_python.h"
+#include "opcode_python.h"
+#include "rrset_python.h"
+#include "message_python.h"
+#include "messagerenderer_python.h"
+#include "tsig_python.h"
+#include "tsigrecord_python.h"
+#include "pydnspp_common.h"
+
+using namespace std;
 using namespace isc::dns;
+using namespace isc::dns::python;
 using namespace isc::util;
 
 namespace {
-//
-// Declaration of the custom exceptions
-// Initialization and addition of these go in the initModulePart
-// function at the end of this file
-//
-PyObject* po_MessageTooShort;
-PyObject* po_InvalidMessageSection;
-PyObject* po_InvalidMessageOperation;
-PyObject* po_InvalidMessageUDPSize;
-
-//
-// 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
-
-//
-// Message
-//
-
-// The s_* Class simply coverst one instantiation of the object
 class s_Message : public PyObject {
 public:
-    Message* message;
+    isc::dns::Message* cppobj;
 };
 
-//
-// We declare the functions here, the definitions are below
-// the type definition of the object, since both can use the other
-//
-
-// General creation and destruction
 int Message_init(s_Message* self, PyObject* args);
 void Message_destroy(s_Message* self);
 
@@ -178,59 +168,6 @@ PyMethodDef Message_methods[] = {
     { NULL, NULL, 0, NULL }
 };
 
-// This defines the complete type for reflection in python and
-// parsing of PyObject* to s_Message
-// Most of the functions are not actually implemented and NULL here.
-PyTypeObject message_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "pydnspp.Message",
-    sizeof(s_Message),                  // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)Message_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
-    Message_str,                        // tp_str
-    NULL,                               // tp_getattro
-    NULL,                               // tp_setattro
-    NULL,                               // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "The Message class encapsulates a standard DNS message.",
-    NULL,                               // tp_traverse
-    NULL,                               // tp_clear
-    NULL,                               // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    NULL,                               // tp_iter
-    NULL,                               // tp_iternext
-    Message_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)Message_init,             // tp_init
-    NULL,                               // tp_alloc
-    PyType_GenericNew,                  // tp_new
-    NULL,                               // tp_free
-    NULL,                               // tp_is_gc
-    NULL,                               // tp_bases
-    NULL,                               // tp_mro
-    NULL,                               // tp_cache
-    NULL,                               // tp_subclasses
-    NULL,                               // tp_weaklist
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
 int
 Message_init(s_Message* self, PyObject* args) {
     int i;
@@ -238,10 +175,10 @@ Message_init(s_Message* self, PyObject* args) {
     if (PyArg_ParseTuple(args, "i", &i)) {
         PyErr_Clear();
         if (i == Message::PARSE) {
-            self->message = new Message(Message::PARSE);
+            self->cppobj = new Message(Message::PARSE);
             return (0);
         } else if (i == Message::RENDER) {
-            self->message = new Message(Message::RENDER);
+            self->cppobj = new Message(Message::RENDER);
             return (0);
         } else {
             PyErr_SetString(PyExc_TypeError, "Message mode must be Message.PARSE or Message.RENDER");
@@ -256,8 +193,8 @@ Message_init(s_Message* self, PyObject* args) {
 
 void
 Message_destroy(s_Message* self) {
-    delete self->message;
-    self->message = NULL;
+    delete self->cppobj;
+    self->cppobj = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
@@ -271,7 +208,7 @@ Message_getHeaderFlag(s_Message* self, PyObject* args) {
         return (NULL);
     }
 
-    if (self->message->getHeaderFlag(
+    if (self->cppobj->getHeaderFlag(
             static_cast<Message::HeaderFlag>(messageflag))) {
         Py_RETURN_TRUE;
     } else {
@@ -296,7 +233,7 @@ Message_setHeaderFlag(s_Message* self, PyObject* args) {
     }
 
     try {
-        self->message->setHeaderFlag(
+        self->cppobj->setHeaderFlag(
             static_cast<Message::HeaderFlag>(messageflag), on == Py_True);
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
@@ -312,7 +249,7 @@ Message_setHeaderFlag(s_Message* self, PyObject* args) {
 
 PyObject*
 Message_getQid(s_Message* self) {
-    return (Py_BuildValue("I", self->message->getQid()));
+    return (Py_BuildValue("I", self->cppobj->getQid()));
 }
 
 PyObject*
@@ -331,7 +268,7 @@ Message_setQid(s_Message* self, PyObject* args) {
     }
 
     try {
-        self->message->setQid(id);
+        self->cppobj->setQid(id);
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -341,35 +278,25 @@ Message_setQid(s_Message* self, PyObject* args) {
 
 PyObject*
 Message_getRcode(s_Message* self) {
-    s_Rcode* rcode;
-
-    rcode = static_cast<s_Rcode*>(rcode_type.tp_alloc(&rcode_type, 0));
-    if (rcode != NULL) {
-        rcode->cppobj = NULL;
-        try {
-            rcode->cppobj = new Rcode(self->message->getRcode());
-        } catch (const InvalidMessageOperation& imo) {
-            PyErr_SetString(po_InvalidMessageOperation, imo.what());
-        } catch (...) {
-            PyErr_SetString(po_IscException, "Unexpected exception");
-        }
-        if (rcode->cppobj == NULL) {
-            Py_DECREF(rcode);
-            return (NULL);
-        }
+    try {
+        return (createRcodeObject(self->cppobj->getRcode()));
+    } catch (const InvalidMessageOperation& imo) {
+        PyErr_SetString(po_InvalidMessageOperation, imo.what());
+        return (NULL);
+    } catch (...) {
+        PyErr_SetString(po_IscException, "Unexpected exception");
+        return (NULL);
     }
-
-    return (rcode);
 }
 
 PyObject*
 Message_setRcode(s_Message* self, PyObject* args) {
-    s_Rcode* rcode;
+    PyObject* rcode;
     if (!PyArg_ParseTuple(args, "O!", &rcode_type, &rcode)) {
         return (NULL);
     }
     try {
-        self->message->setRcode(*rcode->cppobj);
+        self->cppobj->setRcode(PyRcode_ToRcode(rcode));
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -379,35 +306,31 @@ Message_setRcode(s_Message* self, PyObject* args) {
 
 PyObject*
 Message_getOpcode(s_Message* self) {
-    s_Opcode* opcode;
-
-    opcode = static_cast<s_Opcode*>(opcode_type.tp_alloc(&opcode_type, 0));
-    if (opcode != NULL) {
-        opcode->opcode = NULL;
-        try {
-            opcode->opcode = new Opcode(self->message->getOpcode());
-        } catch (const InvalidMessageOperation& imo) {
-            PyErr_SetString(po_InvalidMessageOperation, imo.what());
-        } catch (...) {
-            PyErr_SetString(po_IscException, "Unexpected exception");
-        }
-        if (opcode->opcode == NULL) {
-            Py_DECREF(opcode);
-            return (NULL);
-        }
+    try {
+        return (createOpcodeObject(self->cppobj->getOpcode()));
+    } catch (const InvalidMessageOperation& imo) {
+        PyErr_SetString(po_InvalidMessageOperation, imo.what());
+        return (NULL);
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Failed to get message opcode: " + string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+        return (NULL);
+    } catch (...) {
+        PyErr_SetString(po_IscException,
+                        "Unexpected exception getting opcode from message");
+        return (NULL);
     }
-
-    return (opcode);
 }
 
 PyObject*
 Message_setOpcode(s_Message* self, PyObject* args) {
-    s_Opcode* opcode;
+    PyObject* opcode;
     if (!PyArg_ParseTuple(args, "O!", &opcode_type, &opcode)) {
         return (NULL);
     }
     try {
-        self->message->setOpcode(*opcode->opcode);
+        self->cppobj->setOpcode(PyOpcode_ToOpcode(opcode));
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -417,32 +340,31 @@ Message_setOpcode(s_Message* self, PyObject* args) {
 
 PyObject*
 Message_getEDNS(s_Message* self) {
-    s_EDNS* edns;
-    EDNS* edns_body;
-    ConstEDNSPtr src = self->message->getEDNS();
-
+    ConstEDNSPtr src = self->cppobj->getEDNS();
     if (!src) {
         Py_RETURN_NONE;
     }
-    if ((edns_body = new(nothrow) EDNS(*src)) == NULL) {
-        return (PyErr_NoMemory());
-    }
-    edns = static_cast<s_EDNS*>(opcode_type.tp_alloc(&edns_type, 0));
-    if (edns != NULL) {
-        edns->edns = edns_body;
+    try {
+        return (createEDNSObject(*src));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Failed to get EDNS from message: " + string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting EDNS from message");
     }
-
-    return (edns);
+    return (NULL);
 }
 
 PyObject*
 Message_setEDNS(s_Message* self, PyObject* args) {
-    s_EDNS* edns;
+    PyObject* edns;
     if (!PyArg_ParseTuple(args, "O!", &edns_type, &edns)) {
         return (NULL);
     }
     try {
-        self->message->setEDNS(EDNSPtr(new EDNS(*edns->edns)));
+        self->cppobj->setEDNS(EDNSPtr(new EDNS(PyEDNS_ToEDNS(edns))));
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -453,7 +375,7 @@ Message_setEDNS(s_Message* self, PyObject* args) {
 PyObject*
 Message_getTSIGRecord(s_Message* self) {
     try {
-        const TSIGRecord* tsig_record = self->message->getTSIGRecord();
+        const TSIGRecord* tsig_record = self->cppobj->getTSIGRecord();
 
         if (tsig_record == NULL) {
             Py_RETURN_NONE;
@@ -483,7 +405,7 @@ Message_getRRCount(s_Message* self, PyObject* args) {
         return (NULL);
     }
     try {
-        return (Py_BuildValue("I", self->message->getRRCount(
+        return (Py_BuildValue("I", self->cppobj->getRRCount(
                                   static_cast<Message::Section>(section))));
     } catch (const isc::OutOfRange& ex) {
         PyErr_SetString(PyExc_OverflowError, ex.what());
@@ -496,8 +418,8 @@ PyObject*
 Message_getQuestion(s_Message* self) {
     QuestionIterator qi, qi_end;
     try {
-        qi = self->message->beginQuestion();
-        qi_end = self->message->endQuestion();
+        qi = self->cppobj->beginQuestion();
+        qi_end = self->cppobj->endQuestion();
     } catch (const InvalidMessageSection& ex) {
         PyErr_SetString(po_InvalidMessageSection, ex.what());
         return (NULL);
@@ -512,23 +434,25 @@ Message_getQuestion(s_Message* self) {
         return (NULL);
     }
 
-    for (; qi != qi_end; ++qi) {
-        s_Question *question = static_cast<s_Question*>(
-            question_type.tp_alloc(&question_type, 0));
-        if (question == NULL) {
-            Py_DECREF(question);
-            Py_DECREF(list);
-            return (NULL);
-        }
-        question->question = *qi;
-        if (PyList_Append(list, question) == -1) {
-            Py_DECREF(question);
-            Py_DECREF(list);
-            return (NULL);
+    try {
+        for (; qi != qi_end; ++qi) {
+            if (PyList_Append(list, createQuestionObject(**qi)) == -1) {
+                Py_DECREF(list);
+                return (NULL);
+            }
         }
-        Py_DECREF(question);
+        return (list);
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting Question section: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting Question section");
     }
-    return (list);
+    Py_DECREF(list);
+    return (NULL);
 }
 
 PyObject*
@@ -542,9 +466,9 @@ Message_getSection(s_Message* self, PyObject* args) {
     }
     RRsetIterator rrsi, rrsi_end;
     try {
-        rrsi = self->message->beginSection(
+        rrsi = self->cppobj->beginSection(
             static_cast<Message::Section>(section));
-        rrsi_end = self->message->endSection(
+        rrsi_end = self->cppobj->endSection(
             static_cast<Message::Section>(section));
     } catch (const isc::OutOfRange& ex) {
         PyErr_SetString(PyExc_OverflowError, ex.what());
@@ -562,25 +486,25 @@ Message_getSection(s_Message* self, PyObject* args) {
     if (list == NULL) {
         return (NULL);
     }
-    for (; rrsi != rrsi_end; ++rrsi) {
-        s_RRset *rrset = static_cast<s_RRset*>(
-            rrset_type.tp_alloc(&rrset_type, 0));
-        if (rrset == NULL) {
-                Py_DECREF(rrset);
-                Py_DECREF(list);
-                return (NULL);
-        }
-        rrset->rrset = *rrsi;
-        if (PyList_Append(list, rrset) == -1) {
-                Py_DECREF(rrset);
-                Py_DECREF(list);
-                return (NULL);
+    try {
+        for (; rrsi != rrsi_end; ++rrsi) {
+            if (PyList_Append(list, createRRsetObject(**rrsi)) == -1) {
+                    Py_DECREF(list);
+                    return (NULL);
+            }
         }
-        // PyList_Append increases refcount, so we remove ours since
-        // we don't need it anymore
-        Py_DECREF(rrset);
+        return (list);
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure creating Question object: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure creating Question object");
     }
-    return (list);
+    Py_DECREF(list);
+    return (NULL);
 }
 
 //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
@@ -590,14 +514,14 @@ Message_getSection(s_Message* self, PyObject* args) {
 //static PyObject* Message_addQuestion(s_Message* self, PyObject* args);
 PyObject*
 Message_addQuestion(s_Message* self, PyObject* args) {
-    s_Question *question;
+    PyObject* question;
 
     if (!PyArg_ParseTuple(args, "O!", &question_type, &question)) {
         return (NULL);
     }
 
-    self->message->addQuestion(question->question);
-    
+    self->cppobj->addQuestion(PyQuestion_ToQuestion(question));
+
     Py_RETURN_NONE;
 }
 
@@ -605,15 +529,15 @@ PyObject*
 Message_addRRset(s_Message* self, PyObject* args) {
     PyObject *sign = Py_False;
     int section;
-    s_RRset* rrset;
+    PyObject* rrset;
     if (!PyArg_ParseTuple(args, "iO!|O!", &section, &rrset_type, &rrset,
                           &PyBool_Type, &sign)) {
         return (NULL);
     }
 
     try {
-        self->message->addRRset(static_cast<Message::Section>(section),
-                                rrset->rrset, sign == Py_True);
+        self->cppobj->addRRset(static_cast<Message::Section>(section),
+                               PyRRset_ToRRsetPtr(rrset), sign == Py_True);
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -634,10 +558,10 @@ Message_clear(s_Message* self, PyObject* args) {
     if (PyArg_ParseTuple(args, "i", &i)) {
         PyErr_Clear();
         if (i == Message::PARSE) {
-            self->message->clear(Message::PARSE);
+            self->cppobj->clear(Message::PARSE);
             Py_RETURN_NONE;
         } else if (i == Message::RENDER) {
-            self->message->clear(Message::RENDER);
+            self->cppobj->clear(Message::RENDER);
             Py_RETURN_NONE;
         } else {
             PyErr_SetString(PyExc_TypeError,
@@ -651,7 +575,7 @@ Message_clear(s_Message* self, PyObject* args) {
 
 PyObject*
 Message_makeResponse(s_Message* self) {
-    self->message->makeResponse();
+    self->cppobj->makeResponse();
     Py_RETURN_NONE;
 }
 
@@ -659,7 +583,7 @@ PyObject*
 Message_toText(s_Message* self) {
     // Py_BuildValue makes python objects from native data
     try {
-        return (Py_BuildValue("s", self->message->toText().c_str()));
+        return (Py_BuildValue("s", self->cppobj->toText().c_str()));
     } catch (const InvalidMessageOperation& imo) {
         PyErr_Clear();
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -680,16 +604,17 @@ Message_str(PyObject* self) {
 
 PyObject*
 Message_toWire(s_Message* self, PyObject* args) {
-    s_MessageRenderer* mr;
-    s_TSIGContext* tsig_ctx = NULL;
-    
+    PyObject* mr;
+    PyObject* tsig_ctx = NULL;
+
     if (PyArg_ParseTuple(args, "O!|O!", &messagerenderer_type, &mr,
                          &tsigcontext_type, &tsig_ctx)) {
         try {
             if (tsig_ctx == NULL) {
-                self->message->toWire(*mr->messagerenderer);
+                self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
             } else {
-                self->message->toWire(*mr->messagerenderer, *tsig_ctx->cppobj);
+                self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr),
+                                     PyTSIGContext_ToTSIGContext(tsig_ctx));
             }
             // If we return NULL it is seen as an error, so use this for
             // None returns
@@ -727,10 +652,10 @@ Message_fromWire(s_Message* self, PyObject* args) {
     if (!PyArg_ParseTuple(args, "y#", &b, &len)) {
         return (NULL);
     }
-    
+
     InputBuffer inbuf(b, len);
     try {
-        self->message->fromWire(inbuf);
+        self->cppobj->fromWire(inbuf);
         Py_RETURN_NONE;
     } catch (const InvalidMessageOperation& imo) {
         PyErr_SetString(po_InvalidMessageOperation, imo.what());
@@ -747,71 +672,75 @@ Message_fromWire(s_Message* self, PyObject* args) {
     }
 }
 
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_Message(PyObject* mod) {
-    if (PyType_Ready(&message_type) < 0) {
-        return (false);
-    }
-    Py_INCREF(&message_type);
-    
-    // Class variables
-    // These are added to the tp_dict of the type object
-    //
-    addClassVariable(message_type, "PARSE",
-                     Py_BuildValue("I", Message::PARSE));
-    addClassVariable(message_type, "RENDER",
-                     Py_BuildValue("I", Message::RENDER));
-
-    addClassVariable(message_type, "HEADERFLAG_QR",
-                     Py_BuildValue("I", Message::HEADERFLAG_QR));
-    addClassVariable(message_type, "HEADERFLAG_AA",
-                     Py_BuildValue("I", Message::HEADERFLAG_AA));
-    addClassVariable(message_type, "HEADERFLAG_TC",
-                     Py_BuildValue("I", Message::HEADERFLAG_TC));
-    addClassVariable(message_type, "HEADERFLAG_RD",
-                     Py_BuildValue("I", Message::HEADERFLAG_RD));
-    addClassVariable(message_type, "HEADERFLAG_RA",
-                     Py_BuildValue("I", Message::HEADERFLAG_RA));
-    addClassVariable(message_type, "HEADERFLAG_AD",
-                     Py_BuildValue("I", Message::HEADERFLAG_AD));
-    addClassVariable(message_type, "HEADERFLAG_CD",
-                     Py_BuildValue("I", Message::HEADERFLAG_CD));
-
-    addClassVariable(message_type, "SECTION_QUESTION",
-                     Py_BuildValue("I", Message::SECTION_QUESTION));
-    addClassVariable(message_type, "SECTION_ANSWER",
-                     Py_BuildValue("I", Message::SECTION_ANSWER));
-    addClassVariable(message_type, "SECTION_AUTHORITY",
-                     Py_BuildValue("I", Message::SECTION_AUTHORITY));
-    addClassVariable(message_type, "SECTION_ADDITIONAL",
-                     Py_BuildValue("I", Message::SECTION_ADDITIONAL));
-
-    addClassVariable(message_type, "DEFAULT_MAX_UDPSIZE",
-                     Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE));
-
-    /* Class-specific exceptions */
-    po_MessageTooShort = PyErr_NewException("pydnspp.MessageTooShort", NULL,
-                                            NULL);
-    PyModule_AddObject(mod, "MessageTooShort", po_MessageTooShort);
-    po_InvalidMessageSection =
-        PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidMessageSection", po_InvalidMessageSection);
-    po_InvalidMessageOperation =
-        PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidMessageOperation",
-                       po_InvalidMessageOperation);
-    po_InvalidMessageUDPSize =
-        PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidMessageUDPSize", po_InvalidMessageUDPSize);
-    po_DNSMessageBADVERS = PyErr_NewException("pydnspp.DNSMessageBADVERS",
-                                              NULL, NULL);
-    PyModule_AddObject(mod, "DNSMessageBADVERS", po_DNSMessageBADVERS);
-
-    PyModule_AddObject(mod, "Message",
-                       reinterpret_cast<PyObject*>(&message_type));
-
-
-    return (true);
-}
 } // end of unnamed namespace
+
+namespace isc {
+namespace dns {
+namespace python {
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function in pydnspp.cc
+//
+PyObject* po_MessageTooShort;
+PyObject* po_InvalidMessageSection;
+PyObject* po_InvalidMessageOperation;
+PyObject* po_InvalidMessageUDPSize;
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_Message
+// Most of the functions are not actually implemented and NULL here.
+PyTypeObject message_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.Message",
+    sizeof(s_Message),                  // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)Message_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
+    Message_str,                        // tp_str
+    NULL,                               // tp_getattro
+    NULL,                               // tp_setattro
+    NULL,                               // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "The Message class encapsulates a standard DNS message.",
+    NULL,                               // tp_traverse
+    NULL,                               // tp_clear
+    NULL,                               // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    NULL,                               // tp_iter
+    NULL,                               // tp_iternext
+    Message_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)Message_init,             // tp_init
+    NULL,                               // tp_alloc
+    PyType_GenericNew,                  // tp_new
+    NULL,                               // tp_free
+    NULL,                               // tp_is_gc
+    NULL,                               // tp_bases
+    NULL,                               // tp_mro
+    NULL,                               // tp_cache
+    NULL,                               // tp_subclasses
+    NULL,                               // tp_weaklist
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+} // end python namespace
+} // end dns namespace
+} // end isc namespace
diff --git a/src/lib/dns/python/message_python.h b/src/lib/dns/python/message_python.h
new file mode 100644
index 0000000..be23890
--- /dev/null
+++ b/src/lib/dns/python/message_python.h
@@ -0,0 +1,40 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_MESSAGE_H
+#define __PYTHON_MESSAGE_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class Message;
+
+namespace python {
+
+extern PyObject* po_MessageTooShort;
+extern PyObject* po_InvalidMessageSection;
+extern PyObject* po_InvalidMessageOperation;
+extern PyObject* po_InvalidMessageUDPSize;
+
+extern PyTypeObject message_type;
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_MESSAGE_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/messagerenderer_python.cc b/src/lib/dns/python/messagerenderer_python.cc
index e6f5d3e..bb89622 100644
--- a/src/lib/dns/python/messagerenderer_python.cc
+++ b/src/lib/dns/python/messagerenderer_python.cc
@@ -17,6 +17,7 @@
 #include <util/buffer.h>
 
 #include <dns/messagerenderer.h>
+#include <util/python/pycppwrapper_util.h>
 
 #include "pydnspp_common.h"
 #include "messagerenderer_python.h"
@@ -24,15 +25,21 @@
 using namespace isc::dns;
 using namespace isc::dns::python;
 using namespace isc::util;
-
-// MessageRenderer
-
-s_MessageRenderer::s_MessageRenderer() : outputbuffer(NULL),
-                                         messagerenderer(NULL)
-{
-}
+using namespace isc::util::python;
 
 namespace {
+// The s_* Class simply covers one instantiation of the object.
+//
+// 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.
+class s_MessageRenderer : public PyObject {
+public:
+    s_MessageRenderer();
+    isc::util::OutputBuffer* outputbuffer;
+    MessageRenderer* cppobj;
+};
+
 int MessageRenderer_init(s_MessageRenderer* self);
 void MessageRenderer_destroy(s_MessageRenderer* self);
 
@@ -72,15 +79,15 @@ PyMethodDef MessageRenderer_methods[] = {
 int
 MessageRenderer_init(s_MessageRenderer* self) {
     self->outputbuffer = new OutputBuffer(4096);
-    self->messagerenderer = new MessageRenderer(*self->outputbuffer);
+    self->cppobj = new MessageRenderer(*self->outputbuffer);
     return (0);
 }
 
 void
 MessageRenderer_destroy(s_MessageRenderer* self) {
-    delete self->messagerenderer;
+    delete self->cppobj;
     delete self->outputbuffer;
-    self->messagerenderer = NULL;
+    self->cppobj = NULL;
     self->outputbuffer = NULL;
     Py_TYPE(self)->tp_free(self);
 }
@@ -88,18 +95,18 @@ MessageRenderer_destroy(s_MessageRenderer* self) {
 PyObject*
 MessageRenderer_getData(s_MessageRenderer* self) {
     return (Py_BuildValue("y#",
-                         self->messagerenderer->getData(),
-                          self->messagerenderer->getLength()));
+                          self->cppobj->getData(),
+                          self->cppobj->getLength()));
 }
 
 PyObject*
 MessageRenderer_getLength(s_MessageRenderer* self) {
-    return (Py_BuildValue("I", self->messagerenderer->getLength()));
+    return (Py_BuildValue("I", self->cppobj->getLength()));
 }
 
 PyObject*
 MessageRenderer_isTruncated(s_MessageRenderer* self) {
-    if (self->messagerenderer->isTruncated()) {
+    if (self->cppobj->isTruncated()) {
         Py_RETURN_TRUE;
     } else {
         Py_RETURN_FALSE;
@@ -108,17 +115,17 @@ MessageRenderer_isTruncated(s_MessageRenderer* self) {
 
 PyObject*
 MessageRenderer_getLengthLimit(s_MessageRenderer* self) {
-    return (Py_BuildValue("I", self->messagerenderer->getLengthLimit()));
+    return (Py_BuildValue("I", self->cppobj->getLengthLimit()));
 }
 
 PyObject*
 MessageRenderer_getCompressMode(s_MessageRenderer* self) {
-    return (Py_BuildValue("I", self->messagerenderer->getCompressMode()));
+    return (Py_BuildValue("I", self->cppobj->getCompressMode()));
 }
 
 PyObject*
 MessageRenderer_setTruncated(s_MessageRenderer* self) {
-    self->messagerenderer->setTruncated();
+    self->cppobj->setTruncated();
     Py_RETURN_NONE;
 }
 
@@ -138,7 +145,7 @@ MessageRenderer_setLengthLimit(s_MessageRenderer* self,
                         "MessageRenderer length limit out of range");
         return (NULL);
     }
-    self->messagerenderer->setLengthLimit(lengthlimit);
+    self->cppobj->setLengthLimit(lengthlimit);
     Py_RETURN_NONE;
 }
 
@@ -152,12 +159,12 @@ MessageRenderer_setCompressMode(s_MessageRenderer* self,
     }
 
     if (mode == MessageRenderer::CASE_INSENSITIVE) {
-        self->messagerenderer->setCompressMode(MessageRenderer::CASE_INSENSITIVE);
+        self->cppobj->setCompressMode(MessageRenderer::CASE_INSENSITIVE);
         // If we return NULL it is seen as an error, so use this for
         // None returns, it also applies to CASE_SENSITIVE.
         Py_RETURN_NONE;
     } else if (mode == MessageRenderer::CASE_SENSITIVE) {
-        self->messagerenderer->setCompressMode(MessageRenderer::CASE_SENSITIVE);
+        self->cppobj->setCompressMode(MessageRenderer::CASE_SENSITIVE);
         Py_RETURN_NONE;
     } else {
         PyErr_SetString(PyExc_TypeError,
@@ -169,12 +176,11 @@ MessageRenderer_setCompressMode(s_MessageRenderer* self,
 
 PyObject*
 MessageRenderer_clear(s_MessageRenderer* self) {
-    self->messagerenderer->clear();
+    self->cppobj->clear();
     Py_RETURN_NONE;
 }
 } // end of unnamed namespace
 
-// end of MessageRenderer
 namespace isc {
 namespace dns {
 namespace python {
@@ -233,37 +239,29 @@ PyTypeObject messagerenderer_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_MessageRenderer(PyObject* mod) {
-    // Add the exceptions to the module
+// If we need a createMessageRendererObject(), should we copy? can we?
+// copy the existing buffer into a new one, then create a new renderer with
+// that buffer?
 
-    // 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
+bool
+PyMessageRenderer_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &messagerenderer_type));
+}
 
-    // NameComparisonResult
-    if (PyType_Ready(&messagerenderer_type) < 0) {
-        return (false);
+MessageRenderer&
+PyMessageRenderer_ToMessageRenderer(PyObject* messagerenderer_obj) {
+    if (messagerenderer_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in MessageRenderer PyObject conversion");
     }
-    Py_INCREF(&messagerenderer_type);
+    s_MessageRenderer* messagerenderer = static_cast<s_MessageRenderer*>(messagerenderer_obj);
+    return (*messagerenderer->cppobj);
+}
 
-    // Class variables
-    // These are added to the tp_dict of the type object
-    addClassVariable(messagerenderer_type, "CASE_INSENSITIVE",
-                     Py_BuildValue("I", MessageRenderer::CASE_INSENSITIVE));
-    addClassVariable(messagerenderer_type, "CASE_SENSITIVE",
-                     Py_BuildValue("I", MessageRenderer::CASE_SENSITIVE));
 
-    PyModule_AddObject(mod, "MessageRenderer",
-                       reinterpret_cast<PyObject*>(&messagerenderer_type));
-    
-    return (true);
-}
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/messagerenderer_python.h b/src/lib/dns/python/messagerenderer_python.h
index 3bb096e..ea9a940 100644
--- a/src/lib/dns/python/messagerenderer_python.h
+++ b/src/lib/dns/python/messagerenderer_python.h
@@ -17,30 +17,35 @@
 
 #include <Python.h>
 
+#include <util/buffer.h>
+
 namespace isc {
-namespace util {
-class OutputBuffer;
-}
 namespace dns {
 class MessageRenderer;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object.
-//
-// 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.
-class s_MessageRenderer : public PyObject {
-public:
-    s_MessageRenderer();
-    isc::util::OutputBuffer* outputbuffer;
-    MessageRenderer* messagerenderer;
-};
-
 extern PyTypeObject messagerenderer_type;
 
-bool initModulePart_MessageRenderer(PyObject* mod);
+/// \brief Checks if the given python object is a MessageRenderer object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type MessageRenderer, false otherwise
+bool PyMessageRenderer_Check(PyObject* obj);
+
+/// \brief Returns a reference to the MessageRenderer object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type MessageRenderer; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyMessageRenderer_Check()
+///
+/// \note This is not a copy; if the MessageRenderer is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param messagerenderer_obj The messagerenderer object to convert
+MessageRenderer& PyMessageRenderer_ToMessageRenderer(PyObject* messagerenderer_obj);
 
 } // namespace python
 } // namespace dns
diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc
index d00c6f7..4043445 100644
--- a/src/lib/dns/python/name_python.cc
+++ b/src/lib/dns/python/name_python.cc
@@ -25,20 +25,25 @@
 #include "messagerenderer_python.h"
 #include "name_python.h"
 
-//
-// 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;
 using namespace isc::dns::python;
 using namespace isc::util;
 using namespace isc::util::python;
 
 namespace {
-// NameComparisonResult
+// The s_* Class simply covers one instantiation of the object.
+class s_NameComparisonResult : public PyObject {
+public:
+    s_NameComparisonResult() : cppobj(NULL) {}
+    NameComparisonResult* cppobj;
+};
+
+class s_Name : public PyObject {
+public:
+    s_Name() : cppobj(NULL), position(0) {}
+    Name* cppobj;
+    size_t position;
+};
 
 int NameComparisonResult_init(s_NameComparisonResult*, PyObject*);
 void NameComparisonResult_destroy(s_NameComparisonResult* self);
@@ -84,9 +89,7 @@ PyObject*
 NameComparisonResult_getRelation(s_NameComparisonResult* self) {
     return (Py_BuildValue("I", self->cppobj->getRelation()));
 }
-// end of NameComparisonResult
 
-// Name
 // Shortcut type which would be convenient for adding class variables safely.
 typedef CPPPyObjectContainer<s_Name, Name> NameContainer;
 
@@ -292,7 +295,7 @@ Name_str(PyObject* self) {
 PyObject*
 Name_toWire(s_Name* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
+    PyObject* mr;
 
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
@@ -306,7 +309,7 @@ Name_toWire(s_Name* self, PyObject* args) {
         Py_DECREF(name_bytes);
         return (result);
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-        self->cppobj->toWire(*mr->messagerenderer);
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
         // If we return NULL it is seen as an error, so use this for
         // None returns
         Py_RETURN_NONE;
@@ -495,7 +498,7 @@ Name_isWildCard(s_Name* self) {
         Py_RETURN_FALSE;
     }
 }
-// end of Name
+
 } // end of unnamed namespace
 
 namespace isc {
@@ -634,94 +637,32 @@ PyTypeObject name_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_Name(PyObject* mod) {
-    // 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);
-
-    // Add the enums to the module
-    po_NameRelation = Py_BuildValue("{i:s,i:s,i:s,i:s}",
-                                    NameComparisonResult::SUPERDOMAIN, "SUPERDOMAIN",
-                                    NameComparisonResult::SUBDOMAIN, "SUBDOMAIN",
-                                    NameComparisonResult::EQUAL, "EQUAL",
-                                    NameComparisonResult::COMMONANCESTOR, "COMMONANCESTOR");
-    addClassVariable(name_comparison_result_type, "NameRelation", po_NameRelation);
-
-    PyModule_AddObject(mod, "NameComparisonResult",
-                       reinterpret_cast<PyObject*>(&name_comparison_result_type));
-
-    //
-    // Name
-    //
-    
-    if (PyType_Ready(&name_type) < 0) {
-        return (false);
-    }
-    Py_INCREF(&name_type);
-
-    // Add the constants to the module
-    addClassVariable(name_type, "MAX_WIRE", Py_BuildValue("I", Name::MAX_WIRE));
-    addClassVariable(name_type, "MAX_LABELS", Py_BuildValue("I", Name::MAX_LABELS));
-    addClassVariable(name_type, "MAX_LABELLEN", Py_BuildValue("I", Name::MAX_LABELLEN));
-    addClassVariable(name_type, "MAX_COMPRESS_POINTER", Py_BuildValue("I", Name::MAX_COMPRESS_POINTER));
-    addClassVariable(name_type, "COMPRESS_POINTER_MARK8", Py_BuildValue("I", Name::COMPRESS_POINTER_MARK8));
-    addClassVariable(name_type, "COMPRESS_POINTER_MARK16", Py_BuildValue("I", Name::COMPRESS_POINTER_MARK16));
-
-    s_Name* root_name = PyObject_New(s_Name, &name_type);
-    root_name->cppobj = new Name(Name::ROOT_NAME());
-    PyObject* po_ROOT_NAME = root_name;
-    addClassVariable(name_type, "ROOT_NAME", po_ROOT_NAME);
-
-    PyModule_AddObject(mod, "Name",
-                       reinterpret_cast<PyObject*>(&name_type));
-    
-
-    // Add the exceptions to the module
-    po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel", NULL, NULL);
-    PyModule_AddObject(mod, "EmptyLabel", po_EmptyLabel);
-
-    po_TooLongName = PyErr_NewException("pydnspp.TooLongName", NULL, NULL);
-    PyModule_AddObject(mod, "TooLongName", po_TooLongName);
-
-    po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel", NULL, NULL);
-    PyModule_AddObject(mod, "TooLongLabel", po_TooLongLabel);
-
-    po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType", NULL, NULL);
-    PyModule_AddObject(mod, "BadLabelType", po_BadLabelType);
-
-    po_BadEscape = PyErr_NewException("pydnspp.BadEscape", NULL, NULL);
-    PyModule_AddObject(mod, "BadEscape", po_BadEscape);
-
-    po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName", NULL, NULL);
-    PyModule_AddObject(mod, "IncompleteName", po_IncompleteName);
-
-    po_InvalidBufferPosition = PyErr_NewException("pydnspp.InvalidBufferPosition", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidBufferPosition", po_InvalidBufferPosition);
-
-    // This one could have gone into the message_python.cc file, but is
-    // already needed here.
-    po_DNSMessageFORMERR = PyErr_NewException("pydnspp.DNSMessageFORMERR", NULL, NULL);
-    PyModule_AddObject(mod, "DNSMessageFORMERR", po_DNSMessageFORMERR);
-
-    return (true);
-}
-
 PyObject*
 createNameObject(const Name& source) {
-    NameContainer container = PyObject_New(s_Name, &name_type);
+    NameContainer container(PyObject_New(s_Name, &name_type));
     container.set(new Name(source));
     return (container.release());
 }
+
+bool
+PyName_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &name_type));
+}
+
+const Name&
+PyName_ToName(const PyObject* name_obj) {
+    if (name_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in Name PyObject conversion");
+    }
+    const s_Name* name = static_cast<const s_Name*>(name_obj);
+    return (*name->cppobj);
+}
+
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/name_python.h b/src/lib/dns/python/name_python.h
index f8e793d..86d7fd0 100644
--- a/src/lib/dns/python/name_python.h
+++ b/src/lib/dns/python/name_python.h
@@ -17,20 +17,12 @@
 
 #include <Python.h>
 
-#include <util/python/pycppwrapper_util.h>
-
 namespace isc {
 namespace dns {
-class NameComparisonResult;
 class Name;
 
 namespace python {
 
-//
-// Declaration of the custom exceptions
-// Initialization and addition of these go in the module init at the
-// end
-//
 extern PyObject* po_EmptyLabel;
 extern PyObject* po_TooLongName;
 extern PyObject* po_TooLongLabel;
@@ -47,25 +39,9 @@ extern PyObject* po_DNSMessageFORMERR;
 //
 extern PyObject* po_NameRelation;
 
-// The s_* Class simply covers one instantiation of the object.
-class s_NameComparisonResult : public PyObject {
-public:
-    s_NameComparisonResult() : cppobj(NULL) {}
-    NameComparisonResult* cppobj;
-};
-
-class s_Name : public PyObject {
-public:
-    s_Name() : cppobj(NULL), position(0) {}
-    Name* cppobj;
-    size_t position;
-};
-
 extern PyTypeObject name_comparison_result_type;
 extern PyTypeObject name_type;
 
-bool initModulePart_Name(PyObject* mod);
-
 /// This is A simple shortcut to create a python Name object (in the
 /// form of a pointer to PyObject) with minimal exception safety.
 /// On success, it returns a valid pointer to PyObject with a reference
@@ -74,6 +50,27 @@ bool initModulePart_Name(PyObject* mod);
 /// This function is expected to be called with in a try block
 /// followed by necessary setup for python exception.
 PyObject* createNameObject(const Name& source);
+
+/// \brief Checks if the given python object is a Name object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type Name, false otherwise
+bool PyName_Check(PyObject* obj);
+
+/// \brief Returns a reference to the Name object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type Name; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyName_Check()
+///
+/// \note This is not a copy; if the Name is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param name_obj The name object to convert
+const Name& PyName_ToName(const PyObject* name_obj);
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/opcode_python.cc b/src/lib/dns/python/opcode_python.cc
index 0e2a30b..50436a9 100644
--- a/src/lib/dns/python/opcode_python.cc
+++ b/src/lib/dns/python/opcode_python.cc
@@ -12,32 +12,31 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <dns/opcode.h>
-
-using namespace isc::dns;
+#include <Python.h>
 
-//
-// Declaration of the custom exceptions (None for this class)
+#include <dns/opcode.h>
+#include <util/python/pycppwrapper_util.h>
 
-//
-// Definition of the classes
-//
+#include "pydnspp_common.h"
+#include "opcode_python.h"
+#include "edns_python.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;
+using namespace isc::dns::python;
+using namespace isc::util;
+using namespace isc::util::python;
 
 namespace {
-//
-// Opcode
-//
+
 class s_Opcode : public PyObject {
 public:
-    s_Opcode() : opcode(NULL), static_code(false) {}
-    const Opcode* opcode;
+    s_Opcode() : cppobj(NULL), static_code(false) {}
+    const isc::dns::Opcode* cppobj;
     bool static_code;
 };
 
+typedef CPPPyObjectContainer<s_Opcode, Opcode> OpcodeContainer;
+
 int Opcode_init(s_Opcode* const self, PyObject* args);
 void Opcode_destroy(s_Opcode* const self);
 
@@ -103,64 +102,13 @@ PyMethodDef Opcode_methods[] = {
     { NULL, NULL, 0, NULL }
 };
 
-PyTypeObject opcode_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "pydnspp.Opcode",
-    sizeof(s_Opcode),                   // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)Opcode_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
-    Opcode_str,                         // tp_str
-    NULL,                               // tp_getattro
-    NULL,                               // tp_setattro
-    NULL,                               // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "The Opcode class objects represent standard OPCODEs "
-    "of the header section of DNS messages.",
-    NULL,                               // tp_traverse
-    NULL,                               // tp_clear
-    (richcmpfunc)Opcode_richcmp,        // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    NULL,                               // tp_iter
-    NULL,                               // tp_iternext
-    Opcode_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)Opcode_init,              // tp_init
-    NULL,                               // tp_alloc
-    PyType_GenericNew,                  // tp_new
-    NULL,                               // tp_free
-    NULL,                               // tp_is_gc
-    NULL,                               // tp_bases
-    NULL,                               // tp_mro
-    NULL,                               // tp_cache
-    NULL,                               // tp_subclasses
-    NULL,                               // tp_weaklist
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
 
 int
 Opcode_init(s_Opcode* const self, PyObject* args) {
     uint8_t code = 0;
     if (PyArg_ParseTuple(args, "b", &code)) {
         try {
-            self->opcode = new Opcode(code);
+            self->cppobj = new Opcode(code);
             self->static_code = false;
         } catch (const isc::OutOfRange& ex) {
             PyErr_SetString(PyExc_OverflowError, ex.what());
@@ -181,22 +129,22 @@ Opcode_init(s_Opcode* const self, PyObject* args) {
 void
 Opcode_destroy(s_Opcode* const self) {
     // Depending on whether we created the rcode or are referring
-    // to a global static one, we do or do not delete self->opcode here
+    // to a global static one, we do or do not delete self->cppobj here
     if (!self->static_code) {
-        delete self->opcode;
+        delete self->cppobj;
     }
-    self->opcode = NULL;
+    self->cppobj = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
 PyObject*
 Opcode_getCode(const s_Opcode* const self) {
-    return (Py_BuildValue("I", self->opcode->getCode()));
+    return (Py_BuildValue("I", self->cppobj->getCode()));
 }
 
 PyObject*
 Opcode_toText(const s_Opcode* const self) {
-    return (Py_BuildValue("s", self->opcode->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
 PyObject*
@@ -211,7 +159,7 @@ PyObject*
 Opcode_createStatic(const Opcode& opcode) {
     s_Opcode* ret = PyObject_New(s_Opcode, &opcode_type);
     if (ret != NULL) {
-        ret->opcode = &opcode;
+        ret->cppobj = &opcode;
         ret->static_code = true;
     }
     return (ret);
@@ -297,7 +245,7 @@ Opcode_RESERVED15(const s_Opcode*) {
     return (Opcode_createStatic(Opcode::RESERVED15()));
 }
 
-PyObject* 
+PyObject*
 Opcode_richcmp(const s_Opcode* const self, const s_Opcode* const other,
                const int op)
 {
@@ -318,10 +266,10 @@ Opcode_richcmp(const s_Opcode* const self, const s_Opcode* const other,
         PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
         return (NULL);
     case Py_EQ:
-        c = (*self->opcode == *other->opcode);
+        c = (*self->cppobj == *other->cppobj);
         break;
     case Py_NE:
-        c = (*self->opcode != *other->opcode);
+        c = (*self->cppobj != *other->cppobj);
         break;
     case Py_GT:
         PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
@@ -336,55 +284,88 @@ Opcode_richcmp(const s_Opcode* const self, const s_Opcode* const other,
         Py_RETURN_FALSE;
 }
 
-// Module Initialization, all statics are initialized here
+} // end of unnamed namespace
+
+namespace isc {
+namespace dns {
+namespace python {
+
+PyTypeObject opcode_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.Opcode",
+    sizeof(s_Opcode),                   // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)Opcode_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
+    Opcode_str,                         // tp_str
+    NULL,                               // tp_getattro
+    NULL,                               // tp_setattro
+    NULL,                               // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "The Opcode class objects represent standard OPCODEs "
+    "of the header section of DNS messages.",
+    NULL,                               // tp_traverse
+    NULL,                               // tp_clear
+    (richcmpfunc)Opcode_richcmp,        // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    NULL,                               // tp_iter
+    NULL,                               // tp_iternext
+    Opcode_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)Opcode_init,              // tp_init
+    NULL,                               // tp_alloc
+    PyType_GenericNew,                  // tp_new
+    NULL,                               // tp_free
+    NULL,                               // tp_is_gc
+    NULL,                               // tp_bases
+    NULL,                               // tp_mro
+    NULL,                               // tp_cache
+    NULL,                               // tp_subclasses
+    NULL,                               // tp_weaklist
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+PyObject*
+createOpcodeObject(const Opcode& source) {
+    OpcodeContainer container(PyObject_New(s_Opcode, &opcode_type));
+    container.set(new Opcode(source));
+    return (container.release());
+}
+
 bool
-initModulePart_Opcode(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&opcode_type) < 0) {
-        return (false);
-    }
-    Py_INCREF(&opcode_type);
-    void* p = &opcode_type;
-    if (PyModule_AddObject(mod, "Opcode", static_cast<PyObject*>(p)) != 0) {
-        Py_DECREF(&opcode_type);
-        return (false);
+PyOpcode_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
+    return (PyObject_TypeCheck(obj, &opcode_type));
+}
 
-    addClassVariable(opcode_type, "QUERY_CODE",
-                     Py_BuildValue("h", Opcode::QUERY_CODE));
-    addClassVariable(opcode_type, "IQUERY_CODE",
-                     Py_BuildValue("h", Opcode::IQUERY_CODE));
-    addClassVariable(opcode_type, "STATUS_CODE",
-                     Py_BuildValue("h", Opcode::STATUS_CODE));
-    addClassVariable(opcode_type, "RESERVED3_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED3_CODE));
-    addClassVariable(opcode_type, "NOTIFY_CODE",
-                     Py_BuildValue("h", Opcode::NOTIFY_CODE));
-    addClassVariable(opcode_type, "UPDATE_CODE",
-                     Py_BuildValue("h", Opcode::UPDATE_CODE));
-    addClassVariable(opcode_type, "RESERVED6_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED6_CODE));
-    addClassVariable(opcode_type, "RESERVED7_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED7_CODE));
-    addClassVariable(opcode_type, "RESERVED8_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED8_CODE));
-    addClassVariable(opcode_type, "RESERVED9_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED9_CODE));
-    addClassVariable(opcode_type, "RESERVED10_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED10_CODE));
-    addClassVariable(opcode_type, "RESERVED11_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED11_CODE));
-    addClassVariable(opcode_type, "RESERVED12_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED12_CODE));
-    addClassVariable(opcode_type, "RESERVED13_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED13_CODE));
-    addClassVariable(opcode_type, "RESERVED14_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED14_CODE));
-    addClassVariable(opcode_type, "RESERVED15_CODE",
-                     Py_BuildValue("h", Opcode::RESERVED15_CODE));
-
-    return (true);
+const Opcode&
+PyOpcode_ToOpcode(const PyObject* opcode_obj) {
+    if (opcode_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in Opcode PyObject conversion");
+    }
+    const s_Opcode* opcode = static_cast<const s_Opcode*>(opcode_obj);
+    return (*opcode->cppobj);
 }
-} // end of unnamed namespace
+
+} // end python namespace
+} // end dns namespace
+} // end isc namespace
diff --git a/src/lib/dns/python/opcode_python.h b/src/lib/dns/python/opcode_python.h
new file mode 100644
index 0000000..d0aec15
--- /dev/null
+++ b/src/lib/dns/python/opcode_python.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_OPCODE_H
+#define __PYTHON_OPCODE_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class Opcode;
+
+namespace python {
+
+extern PyTypeObject opcode_type;
+
+/// This is a simple shortcut to create a python Opcode object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createOpcodeObject(const Opcode& source);
+
+/// \brief Checks if the given python object is a Opcode object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type Opcode, false otherwise
+bool PyOpcode_Check(PyObject* obj);
+
+/// \brief Returns a reference to the Opcode object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type Opcode; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyOpcode_Check()
+///
+/// \note This is not a copy; if the Opcode is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param opcode_obj The opcode object to convert
+const Opcode& PyOpcode_ToOpcode(const PyObject* opcode_obj);
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_OPCODE_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc
index 07abf71..830876c 100644
--- a/src/lib/dns/python/pydnspp.cc
+++ b/src/lib/dns/python/pydnspp.cc
@@ -21,63 +21,680 @@
 // name initModulePart_<name>, and return true/false instead of
 // NULL/*mod
 //
-// And of course care has to be taken that all identifiers be unique
+// The big init function is split up into a separate initModulePart function
+// for each class we add.
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include <structmember.h>
 
-#include <config.h>
-
-#include <exceptions/exceptions.h>
-
-#include <util/buffer.h>
-
-#include <dns/exceptions.h>
-#include <dns/name.h>
-#include <dns/messagerenderer.h>
+#include <dns/message.h>
+#include <dns/opcode.h>
+#include <dns/tsig.h>
+#include <util/python/pycppwrapper_util.h>
 
 #include "pydnspp_common.h"
+
+#include "edns_python.h"
+#include "message_python.h"
 #include "messagerenderer_python.h"
 #include "name_python.h"
+#include "opcode_python.h"
+#include "pydnspp_common.h"
+#include "pydnspp_towire.h"
+#include "question_python.h"
 #include "rcode_python.h"
+#include "rdata_python.h"
+#include "rrclass_python.h"
+#include "rrset_python.h"
+#include "rrttl_python.h"
+#include "rrtype_python.h"
+#include "tsigerror_python.h"
 #include "tsigkey_python.h"
+#include "tsig_python.h"
 #include "tsig_rdata_python.h"
-#include "tsigerror_python.h"
 #include "tsigrecord_python.h"
-#include "tsig_python.h"
 
-namespace isc {
-namespace dns {
-namespace python {
-// For our 'general' isc::Exceptions
-PyObject* po_IscException;
-PyObject* po_InvalidParameter;
+using namespace isc::dns;
+using namespace isc::dns::python;
+using namespace isc::util::python;
+
+namespace {
+
+bool
+initModulePart_EDNS(PyObject* mod) {
+    // We initialize the static description object with PyType_Ready(),
+    // then add it to the module. This is not just a check! (leaving
+    // this out results in segmentation faults)
+    //
+    // After the type has been initialized, we initialize any exceptions
+    // that are defined in the wrapper for this class, and add constants
+    // to the type, if any
+
+    if (PyType_Ready(&edns_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&edns_type);
+    void* p = &edns_type;
+    PyModule_AddObject(mod, "EDNS", static_cast<PyObject*>(p));
+
+    addClassVariable(edns_type, "SUPPORTED_VERSION",
+                     Py_BuildValue("B", EDNS::SUPPORTED_VERSION));
 
-// For our own isc::dns::Exception
-PyObject* po_DNSMessageBADVERS;
+    return (true);
 }
+
+bool
+initModulePart_Message(PyObject* mod) {
+    if (PyType_Ready(&message_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&message_type);
+
+    // Class variables
+    // These are added to the tp_dict of the type object
+    //
+    addClassVariable(message_type, "PARSE",
+                     Py_BuildValue("I", Message::PARSE));
+    addClassVariable(message_type, "RENDER",
+                     Py_BuildValue("I", Message::RENDER));
+
+    addClassVariable(message_type, "HEADERFLAG_QR",
+                     Py_BuildValue("I", Message::HEADERFLAG_QR));
+    addClassVariable(message_type, "HEADERFLAG_AA",
+                     Py_BuildValue("I", Message::HEADERFLAG_AA));
+    addClassVariable(message_type, "HEADERFLAG_TC",
+                     Py_BuildValue("I", Message::HEADERFLAG_TC));
+    addClassVariable(message_type, "HEADERFLAG_RD",
+                     Py_BuildValue("I", Message::HEADERFLAG_RD));
+    addClassVariable(message_type, "HEADERFLAG_RA",
+                     Py_BuildValue("I", Message::HEADERFLAG_RA));
+    addClassVariable(message_type, "HEADERFLAG_AD",
+                     Py_BuildValue("I", Message::HEADERFLAG_AD));
+    addClassVariable(message_type, "HEADERFLAG_CD",
+                     Py_BuildValue("I", Message::HEADERFLAG_CD));
+
+    addClassVariable(message_type, "SECTION_QUESTION",
+                     Py_BuildValue("I", Message::SECTION_QUESTION));
+    addClassVariable(message_type, "SECTION_ANSWER",
+                     Py_BuildValue("I", Message::SECTION_ANSWER));
+    addClassVariable(message_type, "SECTION_AUTHORITY",
+                     Py_BuildValue("I", Message::SECTION_AUTHORITY));
+    addClassVariable(message_type, "SECTION_ADDITIONAL",
+                     Py_BuildValue("I", Message::SECTION_ADDITIONAL));
+
+    addClassVariable(message_type, "DEFAULT_MAX_UDPSIZE",
+                     Py_BuildValue("I", Message::DEFAULT_MAX_UDPSIZE));
+
+    /* Class-specific exceptions */
+    po_MessageTooShort = PyErr_NewException("pydnspp.MessageTooShort", NULL,
+                                            NULL);
+    PyModule_AddObject(mod, "MessageTooShort", po_MessageTooShort);
+    po_InvalidMessageSection =
+        PyErr_NewException("pydnspp.InvalidMessageSection", NULL, NULL);
+    PyModule_AddObject(mod, "InvalidMessageSection", po_InvalidMessageSection);
+    po_InvalidMessageOperation =
+        PyErr_NewException("pydnspp.InvalidMessageOperation", NULL, NULL);
+    PyModule_AddObject(mod, "InvalidMessageOperation",
+                       po_InvalidMessageOperation);
+    po_InvalidMessageUDPSize =
+        PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
+    PyModule_AddObject(mod, "InvalidMessageUDPSize", po_InvalidMessageUDPSize);
+    po_DNSMessageBADVERS = PyErr_NewException("pydnspp.DNSMessageBADVERS",
+                                              NULL, NULL);
+    PyModule_AddObject(mod, "DNSMessageBADVERS", po_DNSMessageBADVERS);
+
+    PyModule_AddObject(mod, "Message",
+                       reinterpret_cast<PyObject*>(&message_type));
+
+
+    return (true);
 }
+
+bool
+initModulePart_MessageRenderer(PyObject* mod) {
+    if (PyType_Ready(&messagerenderer_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&messagerenderer_type);
+
+    addClassVariable(messagerenderer_type, "CASE_INSENSITIVE",
+                     Py_BuildValue("I", MessageRenderer::CASE_INSENSITIVE));
+    addClassVariable(messagerenderer_type, "CASE_SENSITIVE",
+                     Py_BuildValue("I", MessageRenderer::CASE_SENSITIVE));
+
+    PyModule_AddObject(mod, "MessageRenderer",
+                       reinterpret_cast<PyObject*>(&messagerenderer_type));
+
+    return (true);
 }
 
-// order is important here!
-using namespace isc::dns::python;
+bool
+initModulePart_Name(PyObject* mod) {
 
-#include <dns/python/rrclass_python.cc>        // needs Messagerenderer
-#include <dns/python/rrtype_python.cc>         // needs Messagerenderer
-#include <dns/python/rrttl_python.cc>          // needs Messagerenderer
-#include <dns/python/rdata_python.cc>          // needs Type, Class
-#include <dns/python/rrset_python.cc>          // needs Rdata, RRTTL
-#include <dns/python/question_python.cc>       // needs RRClass, RRType, RRTTL,
-                                               // Name
-#include <dns/python/opcode_python.cc>
-#include <dns/python/edns_python.cc>           // needs Messagerenderer, Rcode
-#include <dns/python/message_python.cc>        // needs RRset, Question
+    //
+    // NameComparisonResult
+    //
+    if (PyType_Ready(&name_comparison_result_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&name_comparison_result_type);
+
+    // Add the enums to the module
+    po_NameRelation = Py_BuildValue("{i:s,i:s,i:s,i:s}",
+        NameComparisonResult::SUPERDOMAIN, "SUPERDOMAIN",
+        NameComparisonResult::SUBDOMAIN, "SUBDOMAIN",
+        NameComparisonResult::EQUAL, "EQUAL",
+        NameComparisonResult::COMMONANCESTOR, "COMMONANCESTOR");
+    addClassVariable(name_comparison_result_type, "NameRelation",
+                     po_NameRelation);
+
+    PyModule_AddObject(mod, "NameComparisonResult",
+        reinterpret_cast<PyObject*>(&name_comparison_result_type));
+
+    //
+    // Name
+    //
+
+    if (PyType_Ready(&name_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&name_type);
+
+    // Add the constants to the module
+    addClassVariable(name_type, "MAX_WIRE",
+                     Py_BuildValue("I", Name::MAX_WIRE));
+    addClassVariable(name_type, "MAX_LABELS",
+                     Py_BuildValue("I", Name::MAX_LABELS));
+    addClassVariable(name_type, "MAX_LABELLEN",
+                     Py_BuildValue("I", Name::MAX_LABELLEN));
+    addClassVariable(name_type, "MAX_COMPRESS_POINTER",
+                     Py_BuildValue("I", Name::MAX_COMPRESS_POINTER));
+    addClassVariable(name_type, "COMPRESS_POINTER_MARK8",
+                     Py_BuildValue("I", Name::COMPRESS_POINTER_MARK8));
+    addClassVariable(name_type, "COMPRESS_POINTER_MARK16",
+                     Py_BuildValue("I", Name::COMPRESS_POINTER_MARK16));
+
+    addClassVariable(name_type, "ROOT_NAME",
+                     createNameObject(Name::ROOT_NAME()));
+
+    PyModule_AddObject(mod, "Name",
+                       reinterpret_cast<PyObject*>(&name_type));
+
+
+    // Add the exceptions to the module
+    po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel", NULL, NULL);
+    PyModule_AddObject(mod, "EmptyLabel", po_EmptyLabel);
+
+    po_TooLongName = PyErr_NewException("pydnspp.TooLongName", NULL, NULL);
+    PyModule_AddObject(mod, "TooLongName", po_TooLongName);
+
+    po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel", NULL, NULL);
+    PyModule_AddObject(mod, "TooLongLabel", po_TooLongLabel);
+
+    po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType", NULL, NULL);
+    PyModule_AddObject(mod, "BadLabelType", po_BadLabelType);
+
+    po_BadEscape = PyErr_NewException("pydnspp.BadEscape", NULL, NULL);
+    PyModule_AddObject(mod, "BadEscape", po_BadEscape);
+
+    po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName", NULL, NULL);
+    PyModule_AddObject(mod, "IncompleteName", po_IncompleteName);
+
+    po_InvalidBufferPosition =
+        PyErr_NewException("pydnspp.InvalidBufferPosition", NULL, NULL);
+    PyModule_AddObject(mod, "InvalidBufferPosition", po_InvalidBufferPosition);
+
+    // This one could have gone into the message_python.cc file, but is
+    // already needed here.
+    po_DNSMessageFORMERR = PyErr_NewException("pydnspp.DNSMessageFORMERR",
+                                              NULL, NULL);
+    PyModule_AddObject(mod, "DNSMessageFORMERR", po_DNSMessageFORMERR);
+
+    return (true);
+}
+
+bool
+initModulePart_Opcode(PyObject* mod) {
+    if (PyType_Ready(&opcode_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&opcode_type);
+    void* p = &opcode_type;
+    if (PyModule_AddObject(mod, "Opcode", static_cast<PyObject*>(p)) != 0) {
+        Py_DECREF(&opcode_type);
+        return (false);
+    }
+
+    addClassVariable(opcode_type, "QUERY_CODE",
+                     Py_BuildValue("h", Opcode::QUERY_CODE));
+    addClassVariable(opcode_type, "IQUERY_CODE",
+                     Py_BuildValue("h", Opcode::IQUERY_CODE));
+    addClassVariable(opcode_type, "STATUS_CODE",
+                     Py_BuildValue("h", Opcode::STATUS_CODE));
+    addClassVariable(opcode_type, "RESERVED3_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED3_CODE));
+    addClassVariable(opcode_type, "NOTIFY_CODE",
+                     Py_BuildValue("h", Opcode::NOTIFY_CODE));
+    addClassVariable(opcode_type, "UPDATE_CODE",
+                     Py_BuildValue("h", Opcode::UPDATE_CODE));
+    addClassVariable(opcode_type, "RESERVED6_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED6_CODE));
+    addClassVariable(opcode_type, "RESERVED7_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED7_CODE));
+    addClassVariable(opcode_type, "RESERVED8_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED8_CODE));
+    addClassVariable(opcode_type, "RESERVED9_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED9_CODE));
+    addClassVariable(opcode_type, "RESERVED10_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED10_CODE));
+    addClassVariable(opcode_type, "RESERVED11_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED11_CODE));
+    addClassVariable(opcode_type, "RESERVED12_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED12_CODE));
+    addClassVariable(opcode_type, "RESERVED13_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED13_CODE));
+    addClassVariable(opcode_type, "RESERVED14_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED14_CODE));
+    addClassVariable(opcode_type, "RESERVED15_CODE",
+                     Py_BuildValue("h", Opcode::RESERVED15_CODE));
+
+    return (true);
+}
+
+bool
+initModulePart_Question(PyObject* mod) {
+    if (PyType_Ready(&question_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&question_type);
+    PyModule_AddObject(mod, "Question",
+                       reinterpret_cast<PyObject*>(&question_type));
+
+    return (true);
+}
+
+bool
+initModulePart_Rcode(PyObject* mod) {
+    if (PyType_Ready(&rcode_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&rcode_type);
+    void* p = &rcode_type;
+    if (PyModule_AddObject(mod, "Rcode", static_cast<PyObject*>(p)) != 0) {
+        Py_DECREF(&rcode_type);
+        return (false);
+    }
+
+    addClassVariable(rcode_type, "NOERROR_CODE",
+                     Py_BuildValue("h", Rcode::NOERROR_CODE));
+    addClassVariable(rcode_type, "FORMERR_CODE",
+                     Py_BuildValue("h", Rcode::FORMERR_CODE));
+    addClassVariable(rcode_type, "SERVFAIL_CODE",
+                     Py_BuildValue("h", Rcode::SERVFAIL_CODE));
+    addClassVariable(rcode_type, "NXDOMAIN_CODE",
+                     Py_BuildValue("h", Rcode::NXDOMAIN_CODE));
+    addClassVariable(rcode_type, "NOTIMP_CODE",
+                     Py_BuildValue("h", Rcode::NOTIMP_CODE));
+    addClassVariable(rcode_type, "REFUSED_CODE",
+                     Py_BuildValue("h", Rcode::REFUSED_CODE));
+    addClassVariable(rcode_type, "YXDOMAIN_CODE",
+                     Py_BuildValue("h", Rcode::YXDOMAIN_CODE));
+    addClassVariable(rcode_type, "YXRRSET_CODE",
+                     Py_BuildValue("h", Rcode::YXRRSET_CODE));
+    addClassVariable(rcode_type, "NXRRSET_CODE",
+                     Py_BuildValue("h", Rcode::NXRRSET_CODE));
+    addClassVariable(rcode_type, "NOTAUTH_CODE",
+                     Py_BuildValue("h", Rcode::NOTAUTH_CODE));
+    addClassVariable(rcode_type, "NOTZONE_CODE",
+                     Py_BuildValue("h", Rcode::NOTZONE_CODE));
+    addClassVariable(rcode_type, "RESERVED11_CODE",
+                     Py_BuildValue("h", Rcode::RESERVED11_CODE));
+    addClassVariable(rcode_type, "RESERVED12_CODE",
+                     Py_BuildValue("h", Rcode::RESERVED12_CODE));
+    addClassVariable(rcode_type, "RESERVED13_CODE",
+                     Py_BuildValue("h", Rcode::RESERVED13_CODE));
+    addClassVariable(rcode_type, "RESERVED14_CODE",
+                     Py_BuildValue("h", Rcode::RESERVED14_CODE));
+    addClassVariable(rcode_type, "RESERVED15_CODE",
+                     Py_BuildValue("h", Rcode::RESERVED15_CODE));
+    addClassVariable(rcode_type, "BADVERS_CODE",
+                     Py_BuildValue("h", Rcode::BADVERS_CODE));
+
+    return (true);
+}
+
+bool
+initModulePart_Rdata(PyObject* mod) {
+    if (PyType_Ready(&rdata_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&rdata_type);
+    PyModule_AddObject(mod, "Rdata",
+                       reinterpret_cast<PyObject*>(&rdata_type));
+
+    // Add the exceptions to the class
+    po_InvalidRdataLength = PyErr_NewException("pydnspp.InvalidRdataLength",
+                                               NULL, NULL);
+    PyModule_AddObject(mod, "InvalidRdataLength", po_InvalidRdataLength);
+
+    po_InvalidRdataText = PyErr_NewException("pydnspp.InvalidRdataText",
+                                             NULL, NULL);
+    PyModule_AddObject(mod, "InvalidRdataText", po_InvalidRdataText);
+
+    po_CharStringTooLong = PyErr_NewException("pydnspp.CharStringTooLong",
+                                              NULL, NULL);
+    PyModule_AddObject(mod, "CharStringTooLong", po_CharStringTooLong);
+
+
+    return (true);
+}
+
+bool
+initModulePart_RRClass(PyObject* mod) {
+    po_InvalidRRClass = PyErr_NewException("pydnspp.InvalidRRClass",
+                                           NULL, NULL);
+    Py_INCREF(po_InvalidRRClass);
+    PyModule_AddObject(mod, "InvalidRRClass", po_InvalidRRClass);
+    po_IncompleteRRClass = PyErr_NewException("pydnspp.IncompleteRRClass",
+                                              NULL, NULL);
+    Py_INCREF(po_IncompleteRRClass);
+    PyModule_AddObject(mod, "IncompleteRRClass", po_IncompleteRRClass);
+
+    if (PyType_Ready(&rrclass_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&rrclass_type);
+    PyModule_AddObject(mod, "RRClass",
+                       reinterpret_cast<PyObject*>(&rrclass_type));
+
+    return (true);
+}
+
+bool
+initModulePart_RRset(PyObject* mod) {
+    po_EmptyRRset = PyErr_NewException("pydnspp.EmptyRRset", NULL, NULL);
+    PyModule_AddObject(mod, "EmptyRRset", po_EmptyRRset);
+
+    // NameComparisonResult
+    if (PyType_Ready(&rrset_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&rrset_type);
+    PyModule_AddObject(mod, "RRset",
+                       reinterpret_cast<PyObject*>(&rrset_type));
+
+    return (true);
+}
+
+bool
+initModulePart_RRTTL(PyObject* mod) {
+    po_InvalidRRTTL = PyErr_NewException("pydnspp.InvalidRRTTL", NULL, NULL);
+    PyModule_AddObject(mod, "InvalidRRTTL", po_InvalidRRTTL);
+    po_IncompleteRRTTL = PyErr_NewException("pydnspp.IncompleteRRTTL",
+                                            NULL, NULL);
+    PyModule_AddObject(mod, "IncompleteRRTTL", po_IncompleteRRTTL);
+
+    if (PyType_Ready(&rrttl_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&rrttl_type);
+    PyModule_AddObject(mod, "RRTTL",
+                       reinterpret_cast<PyObject*>(&rrttl_type));
+
+    return (true);
+}
+
+bool
+initModulePart_RRType(PyObject* mod) {
+    // Add the exceptions to the module
+    po_InvalidRRType = PyErr_NewException("pydnspp.InvalidRRType", NULL, NULL);
+    PyModule_AddObject(mod, "InvalidRRType", po_InvalidRRType);
+    po_IncompleteRRType = PyErr_NewException("pydnspp.IncompleteRRType",
+                                             NULL, NULL);
+    PyModule_AddObject(mod, "IncompleteRRType", po_IncompleteRRType);
+
+    if (PyType_Ready(&rrtype_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&rrtype_type);
+    PyModule_AddObject(mod, "RRType",
+                       reinterpret_cast<PyObject*>(&rrtype_type));
+
+    return (true);
+}
+
+bool
+initModulePart_TSIGError(PyObject* mod) {
+    if (PyType_Ready(&tsigerror_type) < 0) {
+        return (false);
+    }
+    void* p = &tsigerror_type;
+    if (PyModule_AddObject(mod, "TSIGError", static_cast<PyObject*>(p)) < 0) {
+        return (false);
+    }
+    Py_INCREF(&tsigerror_type);
+
+    try {
+        // Constant class variables
+        // Error codes (bare values)
+        installClassVariable(tsigerror_type, "BAD_SIG_CODE",
+                             Py_BuildValue("H", TSIGError::BAD_SIG_CODE));
+        installClassVariable(tsigerror_type, "BAD_KEY_CODE",
+                             Py_BuildValue("H", TSIGError::BAD_KEY_CODE));
+        installClassVariable(tsigerror_type, "BAD_TIME_CODE",
+                             Py_BuildValue("H", TSIGError::BAD_TIME_CODE));
+
+        // Error codes (constant objects)
+        installClassVariable(tsigerror_type, "NOERROR",
+                             createTSIGErrorObject(TSIGError::NOERROR()));
+        installClassVariable(tsigerror_type, "FORMERR",
+                             createTSIGErrorObject(TSIGError::FORMERR()));
+        installClassVariable(tsigerror_type, "SERVFAIL",
+                             createTSIGErrorObject(TSIGError::SERVFAIL()));
+        installClassVariable(tsigerror_type, "NXDOMAIN",
+                             createTSIGErrorObject(TSIGError::NXDOMAIN()));
+        installClassVariable(tsigerror_type, "NOTIMP",
+                             createTSIGErrorObject(TSIGError::NOTIMP()));
+        installClassVariable(tsigerror_type, "REFUSED",
+                             createTSIGErrorObject(TSIGError::REFUSED()));
+        installClassVariable(tsigerror_type, "YXDOMAIN",
+                             createTSIGErrorObject(TSIGError::YXDOMAIN()));
+        installClassVariable(tsigerror_type, "YXRRSET",
+                             createTSIGErrorObject(TSIGError::YXRRSET()));
+        installClassVariable(tsigerror_type, "NXRRSET",
+                             createTSIGErrorObject(TSIGError::NXRRSET()));
+        installClassVariable(tsigerror_type, "NOTAUTH",
+                             createTSIGErrorObject(TSIGError::NOTAUTH()));
+        installClassVariable(tsigerror_type, "NOTZONE",
+                             createTSIGErrorObject(TSIGError::NOTZONE()));
+        installClassVariable(tsigerror_type, "RESERVED11",
+                             createTSIGErrorObject(TSIGError::RESERVED11()));
+        installClassVariable(tsigerror_type, "RESERVED12",
+                             createTSIGErrorObject(TSIGError::RESERVED12()));
+        installClassVariable(tsigerror_type, "RESERVED13",
+                             createTSIGErrorObject(TSIGError::RESERVED13()));
+        installClassVariable(tsigerror_type, "RESERVED14",
+                             createTSIGErrorObject(TSIGError::RESERVED14()));
+        installClassVariable(tsigerror_type, "RESERVED15",
+                             createTSIGErrorObject(TSIGError::RESERVED15()));
+        installClassVariable(tsigerror_type, "BAD_SIG",
+                             createTSIGErrorObject(TSIGError::BAD_SIG()));
+        installClassVariable(tsigerror_type, "BAD_KEY",
+                             createTSIGErrorObject(TSIGError::BAD_KEY()));
+        installClassVariable(tsigerror_type, "BAD_TIME",
+                             createTSIGErrorObject(TSIGError::BAD_TIME()));
+    } catch (const std::exception& ex) {
+        const std::string ex_what =
+            "Unexpected failure in TSIGError initialization: " +
+            std::string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+        return (false);
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure in TSIGError initialization");
+        return (false);
+    }
+
+    return (true);
+}
+
+bool
+initModulePart_TSIGKey(PyObject* mod) {
+    if (PyType_Ready(&tsigkey_type) < 0) {
+        return (false);
+    }
+    void* p = &tsigkey_type;
+    if (PyModule_AddObject(mod, "TSIGKey", static_cast<PyObject*>(p)) != 0) {
+        return (false);
+    }
+    Py_INCREF(&tsigkey_type);
+
+    try {
+        // Constant class variables
+        installClassVariable(tsigkey_type, "HMACMD5_NAME",
+                             createNameObject(TSIGKey::HMACMD5_NAME()));
+        installClassVariable(tsigkey_type, "HMACSHA1_NAME",
+                             createNameObject(TSIGKey::HMACSHA1_NAME()));
+        installClassVariable(tsigkey_type, "HMACSHA256_NAME",
+                             createNameObject(TSIGKey::HMACSHA256_NAME()));
+        installClassVariable(tsigkey_type, "HMACSHA224_NAME",
+                             createNameObject(TSIGKey::HMACSHA224_NAME()));
+        installClassVariable(tsigkey_type, "HMACSHA384_NAME",
+                             createNameObject(TSIGKey::HMACSHA384_NAME()));
+        installClassVariable(tsigkey_type, "HMACSHA512_NAME",
+                             createNameObject(TSIGKey::HMACSHA512_NAME()));
+    } catch (const std::exception& ex) {
+        const std::string ex_what =
+            "Unexpected failure in TSIGKey initialization: " +
+            std::string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+        return (false);
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure in TSIGKey initialization");
+        return (false);
+    }
+
+    return (true);
+}
+
+bool
+initModulePart_TSIGKeyRing(PyObject* mod) {
+    if (PyType_Ready(&tsigkeyring_type) < 0) {
+        return (false);
+    }
+    Py_INCREF(&tsigkeyring_type);
+    void* p = &tsigkeyring_type;
+    if (PyModule_AddObject(mod, "TSIGKeyRing",
+                           static_cast<PyObject*>(p)) != 0) {
+        Py_DECREF(&tsigkeyring_type);
+        return (false);
+    }
+
+    addClassVariable(tsigkeyring_type, "SUCCESS",
+                     Py_BuildValue("I", TSIGKeyRing::SUCCESS));
+    addClassVariable(tsigkeyring_type, "EXIST",
+                     Py_BuildValue("I", TSIGKeyRing::EXIST));
+    addClassVariable(tsigkeyring_type, "NOTFOUND",
+                     Py_BuildValue("I", TSIGKeyRing::NOTFOUND));
+
+    return (true);
+}
+
+bool
+initModulePart_TSIGContext(PyObject* mod) {
+    if (PyType_Ready(&tsigcontext_type) < 0) {
+        return (false);
+    }
+    void* p = &tsigcontext_type;
+    if (PyModule_AddObject(mod, "TSIGContext",
+                           static_cast<PyObject*>(p)) < 0) {
+        return (false);
+    }
+    Py_INCREF(&tsigcontext_type);
+
+    try {
+        // Class specific exceptions
+        po_TSIGContextError = PyErr_NewException("pydnspp.TSIGContextError",
+                                                 po_IscException, NULL);
+        PyObjectContainer(po_TSIGContextError).installToModule(
+            mod, "TSIGContextError");
+
+        // Constant class variables
+        installClassVariable(tsigcontext_type, "STATE_INIT",
+                             Py_BuildValue("I", TSIGContext::INIT));
+        installClassVariable(tsigcontext_type, "STATE_SENT_REQUEST",
+                             Py_BuildValue("I", TSIGContext::SENT_REQUEST));
+        installClassVariable(tsigcontext_type, "STATE_RECEIVED_REQUEST",
+                             Py_BuildValue("I", TSIGContext::RECEIVED_REQUEST));
+        installClassVariable(tsigcontext_type, "STATE_SENT_RESPONSE",
+                             Py_BuildValue("I", TSIGContext::SENT_RESPONSE));
+        installClassVariable(tsigcontext_type, "STATE_VERIFIED_RESPONSE",
+                             Py_BuildValue("I",
+                                           TSIGContext::VERIFIED_RESPONSE));
+
+        installClassVariable(tsigcontext_type, "DEFAULT_FUDGE",
+                             Py_BuildValue("H", TSIGContext::DEFAULT_FUDGE));
+    } catch (const std::exception& ex) {
+        const std::string ex_what =
+            "Unexpected failure in TSIGContext initialization: " +
+            std::string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+        return (false);
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure in TSIGContext initialization");
+        return (false);
+    }
+
+    return (true);
+}
+
+bool
+initModulePart_TSIG(PyObject* mod) {
+    if (PyType_Ready(&tsig_type) < 0) {
+        return (false);
+    }
+    void* p = &tsig_type;
+    if (PyModule_AddObject(mod, "TSIG", static_cast<PyObject*>(p)) < 0) {
+        return (false);
+    }
+    Py_INCREF(&tsig_type);
+
+    return (true);
+}
+
+bool
+initModulePart_TSIGRecord(PyObject* mod) {
+    if (PyType_Ready(&tsigrecord_type) < 0) {
+        return (false);
+    }
+    void* p = &tsigrecord_type;
+    if (PyModule_AddObject(mod, "TSIGRecord", static_cast<PyObject*>(p)) < 0) {
+        return (false);
+    }
+    Py_INCREF(&tsigrecord_type);
+
+    try {
+        // Constant class variables
+        installClassVariable(tsigrecord_type, "TSIG_TTL",
+                             Py_BuildValue("I", 0));
+    } catch (const std::exception& ex) {
+        const std::string ex_what =
+            "Unexpected failure in TSIGRecord initialization: " +
+            std::string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+        return (false);
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure in TSIGRecord initialization");
+        return (false);
+    }
+
+    return (true);
+}
 
-//
-// Definition of the module
-//
-namespace {
 PyModuleDef pydnspp = {
     { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
     "pydnspp",
diff --git a/src/lib/dns/python/pydnspp_common.cc b/src/lib/dns/python/pydnspp_common.cc
index 8ca763a..0f0f873 100644
--- a/src/lib/dns/python/pydnspp_common.cc
+++ b/src/lib/dns/python/pydnspp_common.cc
@@ -15,9 +15,45 @@
 #include <Python.h>
 #include <pydnspp_common.h>
 
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+
+#include "pydnspp_common.h"
+#include "messagerenderer_python.h"
+#include "name_python.h"
+#include "rdata_python.h"
+#include "rrclass_python.h"
+#include "rrtype_python.h"
+#include "rrttl_python.h"
+#include "rrset_python.h"
+#include "rcode_python.h"
+#include "opcode_python.h"
+#include "tsigkey_python.h"
+#include "tsig_rdata_python.h"
+#include "tsigerror_python.h"
+#include "tsigrecord_python.h"
+#include "tsig_python.h"
+#include "question_python.h"
+#include "message_python.h"
+
+using namespace isc::dns::python;
+
 namespace isc {
 namespace dns {
 namespace python {
+// For our 'general' isc::Exceptions
+PyObject* po_IscException;
+PyObject* po_InvalidParameter;
+
+// For our own isc::dns::Exception
+PyObject* po_DNSMessageBADVERS;
+
+
 int
 readDataFromSequence(uint8_t *data, size_t len, PyObject* sequence) {
     PyObject* el = NULL;
diff --git a/src/lib/dns/python/pydnspp_common.h b/src/lib/dns/python/pydnspp_common.h
index ed90998..8092b08 100644
--- a/src/lib/dns/python/pydnspp_common.h
+++ b/src/lib/dns/python/pydnspp_common.h
@@ -20,8 +20,6 @@
 #include <stdexcept>
 #include <string>
 
-#include <util/python/pycppwrapper_util.h>
-
 namespace isc {
 namespace dns {
 namespace python {
diff --git a/src/lib/dns/python/pydnspp_towire.h b/src/lib/dns/python/pydnspp_towire.h
index 66362a0..e987a29 100644
--- a/src/lib/dns/python/pydnspp_towire.h
+++ b/src/lib/dns/python/pydnspp_towire.h
@@ -93,10 +93,10 @@ toWireWrapper(const PYSTRUCT* const self, PyObject* args) {
         }
 
         // To MessageRenderer version
-        s_MessageRenderer* renderer;
+        PyObject* renderer;
         if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &renderer)) {
             const unsigned int n = TOWIRECALLER(*self->cppobj)(
-                *renderer->messagerenderer);
+                PyMessageRenderer_ToMessageRenderer(renderer));
 
             return (Py_BuildValue("I", n));
         }
diff --git a/src/lib/dns/python/question_python.cc b/src/lib/dns/python/question_python.cc
index c702f85..44d68a2 100644
--- a/src/lib/dns/python/question_python.cc
+++ b/src/lib/dns/python/question_python.cc
@@ -12,25 +12,34 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
 #include <dns/question.h>
+#include <dns/messagerenderer.h>
+#include <dns/exceptions.h>
+#include <util/buffer.h>
+#include <util/python/pycppwrapper_util.h>
+
+#include "pydnspp_common.h"
+#include "question_python.h"
+#include "name_python.h"
+#include "rrclass_python.h"
+#include "rrtype_python.h"
+#include "messagerenderer_python.h"
+
+using namespace std;
 using namespace isc::dns;
+using namespace isc::dns::python;
+using namespace isc::util;
+using namespace isc::util::python;
+using namespace isc;
 
-//
-// Question
-//
-
-// The s_* Class simply coverst one instantiation of the object
+namespace {
 class s_Question : public PyObject {
 public:
-    QuestionPtr question;
+    isc::dns::QuestionPtr cppobj;
 };
 
-//
-// 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 Question_init(s_Question* self, PyObject* args);
 static void Question_destroy(s_Question* self);
 
@@ -69,60 +78,6 @@ static PyMethodDef Question_methods[] = {
     { NULL, NULL, 0, NULL }
 };
 
-// This defines the complete type for reflection in python and
-// parsing of PyObject* to s_Question
-// Most of the functions are not actually implemented and NULL here.
-static PyTypeObject question_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "pydnspp.Question",
-    sizeof(s_Question),                 // tp_basicsize
-    0,                                  // tp_itemsize
-    (destructor)Question_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
-    Question_str,                       // tp_str
-    NULL,                               // tp_getattro
-    NULL,                               // tp_setattro
-    NULL,                               // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "The Question class encapsulates the common search key of DNS"
-    "lookup, consisting of owner name, RR type and RR class.",
-    NULL,                               // tp_traverse
-    NULL,                               // tp_clear
-    NULL,                               // tp_richcompare
-    0,                                  // tp_weaklistoffset
-    NULL,                               // tp_iter
-    NULL,                               // tp_iternext
-    Question_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)Question_init,            // tp_init
-    NULL,                               // tp_alloc
-    PyType_GenericNew,                  // tp_new
-    NULL,                               // tp_free
-    NULL,                               // tp_is_gc
-    NULL,                               // tp_bases
-    NULL,                               // tp_mro
-    NULL,                               // tp_cache
-    NULL,                               // tp_subclasses
-    NULL,                               // tp_weaklist
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
 static int
 Question_init(s_Question* self, PyObject* args) {
     // Try out the various combinations of arguments to call the
@@ -131,9 +86,9 @@ Question_init(s_Question* self, PyObject* args) {
     // 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)
-    s_Name* name;
-    s_RRClass* rrclass;
-    s_RRType* rrtype;
+    PyObject* name;
+    PyObject* rrclass;
+    PyObject* rrtype;
 
     const char* b;
     Py_ssize_t len;
@@ -141,17 +96,18 @@ Question_init(s_Question* self, PyObject* args) {
 
     try {
         if (PyArg_ParseTuple(args, "O!O!O!", &name_type, &name,
-                                               &rrclass_type, &rrclass,
-                                               &rrtype_type, &rrtype
+                                             &rrclass_type, &rrclass,
+                                             &rrtype_type, &rrtype
            )) {
-            self->question = QuestionPtr(new Question(*name->cppobj, *rrclass->rrclass,
-                                          *rrtype->rrtype));
+            self->cppobj = QuestionPtr(new Question(PyName_ToName(name),
+                                                    PyRRClass_ToRRClass(rrclass),
+                                                    PyRRType_ToRRType(rrtype)));
             return (0);
         } else if (PyArg_ParseTuple(args, "y#|I", &b, &len, &position)) {
             PyErr_Clear();
             InputBuffer inbuf(b, len);
             inbuf.setPosition(position);
-            self->question = QuestionPtr(new Question(inbuf));
+            self->cppobj = QuestionPtr(new Question(inbuf));
             return (0);
         }
     } catch (const DNSMessageFORMERR& dmfe) {
@@ -168,7 +124,7 @@ Question_init(s_Question* self, PyObject* args) {
         return (-1);
     }
 
-    self->question = QuestionPtr();
+    self->cppobj = QuestionPtr();
 
     PyErr_Clear();
     PyErr_SetString(PyExc_TypeError,
@@ -178,52 +134,62 @@ Question_init(s_Question* self, PyObject* args) {
 
 static void
 Question_destroy(s_Question* self) {
-    self->question.reset();
+    self->cppobj.reset();
     Py_TYPE(self)->tp_free(self);
 }
 
 static PyObject*
 Question_getName(s_Question* self) {
-    s_Name* name;
-
-    // is this the best way to do this?
-    name = static_cast<s_Name*>(name_type.tp_alloc(&name_type, 0));
-    if (name != NULL) {
-        name->cppobj = new Name(self->question->getName());
+    try {
+        return (createNameObject(self->cppobj->getName()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting question Name: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting question Name");
     }
-
-    return (name);
+    return (NULL);
 }
 
 static PyObject*
 Question_getType(s_Question* self) {
-    s_RRType* rrtype;
-
-    rrtype = static_cast<s_RRType*>(rrtype_type.tp_alloc(&rrtype_type, 0));
-    if (rrtype != NULL) {
-        rrtype->rrtype = new RRType(self->question->getType());
+    try {
+        return (createRRTypeObject(self->cppobj->getType()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting question RRType: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting question RRType");
     }
-
-    return (rrtype);
+    return (NULL);
 }
 
 static PyObject*
 Question_getClass(s_Question* self) {
-    s_RRClass* rrclass;
-
-    rrclass = static_cast<s_RRClass*>(rrclass_type.tp_alloc(&rrclass_type, 0));
-    if (rrclass != NULL) {
-        rrclass->rrclass = new RRClass(self->question->getClass());
+    try {
+        return (createRRClassObject(self->cppobj->getClass()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting question RRClass: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting question RRClass");
     }
-
-    return (rrclass);
+    return (NULL);
 }
 
-
 static PyObject*
 Question_toText(s_Question* self) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->question->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
 static PyObject*
@@ -237,14 +203,14 @@ Question_str(PyObject* self) {
 static PyObject*
 Question_toWire(s_Question* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
-    
+    PyObject* mr;
+
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
 
         // Max length is Name::MAX_WIRE + rrclass (2) + rrtype (2)
         OutputBuffer buffer(Name::MAX_WIRE + 4);
-        self->question->toWire(buffer);
+        self->cppobj->toWire(buffer);
         PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()),
                                                 buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
@@ -253,7 +219,7 @@ Question_toWire(s_Question* self, PyObject* args) {
         Py_DECREF(n);
         return (result);
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-        self->question->toWire(*mr->messagerenderer);
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
         // If we return NULL it is seen as an error, so use this for
         // None returns
         Py_RETURN_NONE;
@@ -264,23 +230,92 @@ Question_toWire(s_Question* self, PyObject* args) {
     return (NULL);
 }
 
-// end of Question
+} // end of unnamed namespace
+
+namespace isc {
+namespace dns {
+namespace python {
+
+// This defines the complete type for reflection in python and
+// parsing of PyObject* to s_Question
+// Most of the functions are not actually implemented and NULL here.
+PyTypeObject question_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.Question",
+    sizeof(s_Question),                 // tp_basicsize
+    0,                                  // tp_itemsize
+    (destructor)Question_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
+    Question_str,                       // tp_str
+    NULL,                               // tp_getattro
+    NULL,                               // tp_setattro
+    NULL,                               // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "The Question class encapsulates the common search key of DNS"
+    "lookup, consisting of owner name, RR type and RR class.",
+    NULL,                               // tp_traverse
+    NULL,                               // tp_clear
+    NULL,                               // tp_richcompare
+    0,                                  // tp_weaklistoffset
+    NULL,                               // tp_iter
+    NULL,                               // tp_iternext
+    Question_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)Question_init,            // tp_init
+    NULL,                               // tp_alloc
+    PyType_GenericNew,                  // tp_new
+    NULL,                               // tp_free
+    NULL,                               // tp_is_gc
+    NULL,                               // tp_bases
+    NULL,                               // tp_mro
+    NULL,                               // tp_cache
+    NULL,                               // tp_subclasses
+    NULL,                               // tp_weaklist
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
 
+PyObject*
+createQuestionObject(const Question& source) {
+    s_Question* question =
+        static_cast<s_Question*>(question_type.tp_alloc(&question_type, 0));
+    question->cppobj = QuestionPtr(new Question(source));
+    return (question);
+}
 
-// Module Initialization, all statics are initialized here
 bool
-initModulePart_Question(PyObject* mod) {
-    // Add the exceptions to the module
+PyQuestion_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &question_type));
+}
 
-    // 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(&question_type) < 0) {
-        return (false);
+const Question&
+PyQuestion_ToQuestion(const PyObject* question_obj) {
+    if (question_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in Question PyObject conversion");
     }
-    Py_INCREF(&question_type);
-    PyModule_AddObject(mod, "Question",
-                       reinterpret_cast<PyObject*>(&question_type));
-    
-    return (true);
+    const s_Question* question = static_cast<const s_Question*>(question_obj);
+    return (*question->cppobj);
 }
+
+} // end python namespace
+} // end dns namespace
+} // end isc namespace
diff --git a/src/lib/dns/python/question_python.h b/src/lib/dns/python/question_python.h
new file mode 100644
index 0000000..f5d78b1
--- /dev/null
+++ b/src/lib/dns/python/question_python.h
@@ -0,0 +1,66 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_QUESTION_H
+#define __PYTHON_QUESTION_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class Question;
+
+namespace python {
+
+extern PyObject* po_EmptyQuestion;
+
+extern PyTypeObject question_type;
+
+/// This is a simple shortcut to create a python Question object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createQuestionObject(const Question& source);
+
+/// \brief Checks if the given python object is a Question object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type Question, false otherwise
+bool PyQuestion_Check(PyObject* obj);
+
+/// \brief Returns a reference to the Question object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type Question; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyQuestion_Check()
+///
+/// \note This is not a copy; if the Question is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param question_obj The question object to convert
+const Question& PyQuestion_ToQuestion(const PyObject* question_obj);
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_QUESTION_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/rcode_python.cc b/src/lib/dns/python/rcode_python.cc
index b594ad3..42b48e7 100644
--- a/src/lib/dns/python/rcode_python.cc
+++ b/src/lib/dns/python/rcode_python.cc
@@ -15,34 +15,39 @@
 #include <Python.h>
 
 #include <exceptions/exceptions.h>
-
 #include <dns/rcode.h>
+#include <util/python/pycppwrapper_util.h>
 
 #include "pydnspp_common.h"
 #include "rcode_python.h"
 
 using namespace isc::dns;
 using namespace isc::dns::python;
+using namespace isc::util::python;
 
+namespace {
+// The s_* Class simply covers one instantiation of the object.
 //
-// Declaration of the custom exceptions (None for this class)
-
-//
-// 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
-
-//
-// Rcode
+// We added a helper variable static_code here
+// Since we can create Rcodes dynamically with Rcode(int), but also
+// use the static globals (Rcode::NOERROR() etc), we use this
+// variable to see if the code came from one of the latter, in which
+// case Rcode_destroy should not free it (the other option is to
+// allocate new Rcodes for every use of the static ones, but this
+// seems more efficient).
 //
+// Follow-up note: we don't have to use the proxy function in the python lib;
+// we can just define class specific constants directly (see TSIGError).
+// We should make this cleanup later.
+class s_Rcode : public PyObject {
+public:
+    s_Rcode() : cppobj(NULL), static_code(false) {};
+    const Rcode* cppobj;
+    bool static_code;
+};
 
-// Trivial constructor.
-s_Rcode::s_Rcode() : cppobj(NULL), static_code(false) {}
+typedef CPPPyObjectContainer<s_Rcode, Rcode> RcodeContainer;
 
-namespace {
 int Rcode_init(s_Rcode* const self, PyObject* args);
 void Rcode_destroy(s_Rcode* const self);
 
@@ -282,7 +287,7 @@ Rcode_BADVERS(const s_Rcode*) {
     return (Rcode_createStatic(Rcode::BADVERS()));
 }
 
-PyObject* 
+PyObject*
 Rcode_richcmp(const s_Rcode* const self, const s_Rcode* const other,
               const int op)
 {
@@ -376,59 +381,31 @@ PyTypeObject rcode_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
+PyObject*
+createRcodeObject(const Rcode& source) {
+    RcodeContainer container(PyObject_New(s_Rcode, &rcode_type));
+    container.set(new Rcode(source));
+    return (container.release());
+}
+
 bool
-initModulePart_Rcode(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&rcode_type) < 0) {
-        return (false);
-    }
-    Py_INCREF(&rcode_type);
-    void* p = &rcode_type;
-    if (PyModule_AddObject(mod, "Rcode", static_cast<PyObject*>(p)) != 0) {
-        Py_DECREF(&rcode_type);
-        return (false);
+PyRcode_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
+    return (PyObject_TypeCheck(obj, &rcode_type));
+}
 
-    addClassVariable(rcode_type, "NOERROR_CODE",
-                     Py_BuildValue("h", Rcode::NOERROR_CODE));
-    addClassVariable(rcode_type, "FORMERR_CODE",
-                     Py_BuildValue("h", Rcode::FORMERR_CODE));
-    addClassVariable(rcode_type, "SERVFAIL_CODE",
-                     Py_BuildValue("h", Rcode::SERVFAIL_CODE));
-    addClassVariable(rcode_type, "NXDOMAIN_CODE",
-                     Py_BuildValue("h", Rcode::NXDOMAIN_CODE));
-    addClassVariable(rcode_type, "NOTIMP_CODE",
-                     Py_BuildValue("h", Rcode::NOTIMP_CODE));
-    addClassVariable(rcode_type, "REFUSED_CODE",
-                     Py_BuildValue("h", Rcode::REFUSED_CODE));
-    addClassVariable(rcode_type, "YXDOMAIN_CODE",
-                     Py_BuildValue("h", Rcode::YXDOMAIN_CODE));
-    addClassVariable(rcode_type, "YXRRSET_CODE",
-                     Py_BuildValue("h", Rcode::YXRRSET_CODE));
-    addClassVariable(rcode_type, "NXRRSET_CODE",
-                     Py_BuildValue("h", Rcode::NXRRSET_CODE));
-    addClassVariable(rcode_type, "NOTAUTH_CODE",
-                     Py_BuildValue("h", Rcode::NOTAUTH_CODE));
-    addClassVariable(rcode_type, "NOTZONE_CODE",
-                     Py_BuildValue("h", Rcode::NOTZONE_CODE));
-    addClassVariable(rcode_type, "RESERVED11_CODE",
-                     Py_BuildValue("h", Rcode::RESERVED11_CODE));
-    addClassVariable(rcode_type, "RESERVED12_CODE",
-                     Py_BuildValue("h", Rcode::RESERVED12_CODE));
-    addClassVariable(rcode_type, "RESERVED13_CODE",
-                     Py_BuildValue("h", Rcode::RESERVED13_CODE));
-    addClassVariable(rcode_type, "RESERVED14_CODE",
-                     Py_BuildValue("h", Rcode::RESERVED14_CODE));
-    addClassVariable(rcode_type, "RESERVED15_CODE",
-                     Py_BuildValue("h", Rcode::RESERVED15_CODE));
-    addClassVariable(rcode_type, "BADVERS_CODE",
-                     Py_BuildValue("h", Rcode::BADVERS_CODE));
-
-    return (true);
+const Rcode&
+PyRcode_ToRcode(const PyObject* rcode_obj) {
+    if (rcode_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in Rcode PyObject conversion");
+    }
+    const s_Rcode* rcode = static_cast<const s_Rcode*>(rcode_obj);
+    return (*rcode->cppobj);
 }
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/rcode_python.h b/src/lib/dns/python/rcode_python.h
index 9b5e699..a149406 100644
--- a/src/lib/dns/python/rcode_python.h
+++ b/src/lib/dns/python/rcode_python.h
@@ -23,29 +23,36 @@ class Rcode;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object.
-//
-// We added a helper variable static_code here
-// Since we can create Rcodes dynamically with Rcode(int), but also
-// use the static globals (Rcode::NOERROR() etc), we use this
-// variable to see if the code came from one of the latter, in which
-// case Rcode_destroy should not free it (the other option is to
-// allocate new Rcodes for every use of the static ones, but this
-// seems more efficient).
-//
-// Follow-up note: we don't have to use the proxy function in the python lib;
-// we can just define class specific constants directly (see TSIGError).
-// We should make this cleanup later.
-class s_Rcode : public PyObject {
-public:
-    s_Rcode();
-    const Rcode* cppobj;
-    bool static_code;
-};
-
 extern PyTypeObject rcode_type;
 
-bool initModulePart_Rcode(PyObject* mod);
+/// This is a simple shortcut to create a python Rcode object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createRcodeObject(const Rcode& source);
+
+/// \brief Checks if the given python object is a Rcode object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type Rcode, false otherwise
+bool PyRcode_Check(PyObject* obj);
+
+/// \brief Returns a reference to the Rcode object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type Rcode; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRcode_Check()
+///
+/// \note This is not a copy; if the Rcode is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rcode_obj The rcode object to convert
+const Rcode& PyRcode_ToRcode(const PyObject* rcode_obj);
 
 } // namespace python
 } // namespace dns
diff --git a/src/lib/dns/python/rdata_python.cc b/src/lib/dns/python/rdata_python.cc
index faa4f4c..06c0263 100644
--- a/src/lib/dns/python/rdata_python.cc
+++ b/src/lib/dns/python/rdata_python.cc
@@ -12,60 +12,48 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
 #include <dns/rdata.h>
+#include <dns/messagerenderer.h>
+#include <util/buffer.h>
+#include <util/python/pycppwrapper_util.h>
+
+#include "rdata_python.h"
+#include "rrtype_python.h"
+#include "rrclass_python.h"
+#include "messagerenderer_python.h"
+
 using namespace isc::dns;
+using namespace isc::dns::python;
 using namespace isc::util;
+using namespace isc::util::python;
 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
-
-// Using a shared_ptr here should not really be necessary (PyObject
-// is already reference-counted), however internally on the cpp side,
-// not doing so might result in problems, since we can't copy construct
-// rdata field, adding them to rrsets results in a problem when the
-// rrset is destroyed later
+namespace {
 class s_Rdata : public PyObject {
 public:
-    RdataPtr rdata;
+    isc::dns::rdata::ConstRdataPtr cppobj;
 };
 
+typedef CPPPyObjectContainer<s_Rdata, Rdata> RdataContainer;
+
 //
 // 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);
+int Rdata_init(s_Rdata* self, PyObject* args);
+void Rdata_destroy(s_Rdata* self);
 
 // These are the functions we export
-static PyObject* Rdata_toText(s_Rdata* self);
+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);
-static PyObject* RData_richcmp(s_Rdata* self, s_Rdata* other, int op);
+PyObject* Rdata_str(PyObject* self);
+PyObject* Rdata_toWire(s_Rdata* self, PyObject* args);
+PyObject* RData_richcmp(s_Rdata* self, s_Rdata* other, int op);
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -73,7 +61,7 @@ static PyObject* RData_richcmp(s_Rdata* self, s_Rdata* other, int op);
 // 2. Our static function here
 // 3. Argument type
 // 4. Documentation
-static PyMethodDef Rdata_methods[] = {
+PyMethodDef Rdata_methods[] = {
     { "to_text", reinterpret_cast<PyCFunction>(Rdata_toText), METH_NOARGS,
       "Returns the string representation" },
     { "to_wire", reinterpret_cast<PyCFunction>(Rdata_toWire), METH_VARARGS,
@@ -86,64 +74,10 @@ static PyMethodDef Rdata_methods[] = {
     { 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)
-    "pydnspp.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
-    "The Rdata class is an abstract base class that provides "
-    "a set of common interfaces to manipulate concrete RDATA objects.",
-    NULL,                               // tp_traverse
-    NULL,                               // tp_clear
-    (richcmpfunc)RData_richcmp,         // 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
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
-static int
+int
 Rdata_init(s_Rdata* self, PyObject* args) {
-    s_RRType* rrtype;
-    s_RRClass* rrclass;
+    PyObject* rrtype;
+    PyObject* rrclass;
     const char* s;
     const char* data;
     Py_ssize_t len;
@@ -152,34 +86,36 @@ Rdata_init(s_Rdata* self, PyObject* args) {
     if (PyArg_ParseTuple(args, "O!O!s", &rrtype_type, &rrtype,
                                         &rrclass_type, &rrclass,
                                         &s)) {
-        self->rdata = createRdata(*rrtype->rrtype, *rrclass->rrclass, s);
+        self->cppobj = createRdata(PyRRType_ToRRType(rrtype),
+                                   PyRRClass_ToRRClass(rrclass), s);
         return (0);
     } else if (PyArg_ParseTuple(args, "O!O!y#", &rrtype_type, &rrtype,
                                 &rrclass_type, &rrclass, &data, &len)) {
         InputBuffer input_buffer(data, len);
-        self->rdata = createRdata(*rrtype->rrtype, *rrclass->rrclass,
-                                  input_buffer, len);
+        self->cppobj = createRdata(PyRRType_ToRRType(rrtype),
+                                   PyRRClass_ToRRClass(rrclass),
+                                   input_buffer, len);
         return (0);
     }
 
     return (-1);
 }
 
-static void
+void
 Rdata_destroy(s_Rdata* self) {
     // Clear the shared_ptr so that its reference count is zero
     // before we call tp_free() (there is no direct release())
-    self->rdata.reset();
+    self->cppobj.reset();
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
+PyObject*
 Rdata_toText(s_Rdata* self) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->rdata->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
-static PyObject*
+PyObject*
 Rdata_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
@@ -187,16 +123,16 @@ Rdata_str(PyObject* self) {
                                 const_cast<char*>("")));
 }
 
-static PyObject*
+PyObject*
 Rdata_toWire(s_Rdata* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
-    
+    PyObject* mr;
+
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
-        
+
         OutputBuffer buffer(4);
-        self->rdata->toWire(buffer);
+        self->cppobj->toWire(buffer);
         PyObject* rd_bytes = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, rd_bytes);
         // We need to release the object we temporarily created here
@@ -204,7 +140,7 @@ Rdata_toWire(s_Rdata* self, PyObject* args) {
         Py_DECREF(rd_bytes);
         return (result);
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-        self->rdata->toWire(*mr->messagerenderer);
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
         // If we return NULL it is seen as an error, so use this for
         // None returns
         Py_RETURN_NONE;
@@ -215,9 +151,7 @@ Rdata_toWire(s_Rdata* self, PyObject* args) {
     return (NULL);
 }
 
-
-
-static PyObject* 
+PyObject*
 RData_richcmp(s_Rdata* self, s_Rdata* other, int op) {
     bool c;
 
@@ -229,24 +163,24 @@ RData_richcmp(s_Rdata* self, s_Rdata* other, int op) {
 
     switch (op) {
     case Py_LT:
-        c = self->rdata->compare(*other->rdata) < 0;
+        c = self->cppobj->compare(*other->cppobj) < 0;
         break;
     case Py_LE:
-        c = self->rdata->compare(*other->rdata) < 0 ||
-            self->rdata->compare(*other->rdata) == 0;
+        c = self->cppobj->compare(*other->cppobj) < 0 ||
+            self->cppobj->compare(*other->cppobj) == 0;
         break;
     case Py_EQ:
-        c = self->rdata->compare(*other->rdata) == 0;
+        c = self->cppobj->compare(*other->cppobj) == 0;
         break;
     case Py_NE:
-        c = self->rdata->compare(*other->rdata) != 0;
+        c = self->cppobj->compare(*other->cppobj) != 0;
         break;
     case Py_GT:
-        c = self->rdata->compare(*other->rdata) > 0;
+        c = self->cppobj->compare(*other->cppobj) > 0;
         break;
     case Py_GE:
-        c = self->rdata->compare(*other->rdata) > 0 ||
-            self->rdata->compare(*other->rdata) == 0;
+        c = self->cppobj->compare(*other->cppobj) > 0 ||
+            self->cppobj->compare(*other->cppobj) == 0;
         break;
     default:
         PyErr_SetString(PyExc_IndexError,
@@ -258,32 +192,107 @@ RData_richcmp(s_Rdata* self, s_Rdata* other, int op) {
     else
         Py_RETURN_FALSE;
 }
-// end of Rdata
 
+} // end of unnamed namespace
 
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_Rdata(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&rdata_type) < 0) {
-        return (false);
-    }
-    Py_INCREF(&rdata_type);
-    PyModule_AddObject(mod, "Rdata",
-                       reinterpret_cast<PyObject*>(&rdata_type));
+namespace isc {
+namespace dns {
+namespace python {
 
-    // Add the exceptions to the class
-    po_InvalidRdataLength = PyErr_NewException("pydnspp.InvalidRdataLength", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidRdataLength", po_InvalidRdataLength);
 
-    po_InvalidRdataText = PyErr_NewException("pydnspp.InvalidRdataText", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidRdataText", po_InvalidRdataText);
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function in pydnspp
+//
+PyObject* po_InvalidRdataLength;
+PyObject* po_InvalidRdataText;
+PyObject* po_CharStringTooLong;
 
-    po_CharStringTooLong = PyErr_NewException("pydnspp.CharStringTooLong", NULL, NULL);
-    PyModule_AddObject(mod, "CharStringTooLong", po_CharStringTooLong);
+// 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.
+PyTypeObject rdata_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.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
+    "The Rdata class is an abstract base class that provides "
+    "a set of common interfaces to manipulate concrete RDATA objects.",
+    NULL,                               // tp_traverse
+    NULL,                               // tp_clear
+    (richcmpfunc)RData_richcmp,         // 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
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
 
-    
-    return (true);
+PyObject*
+createRdataObject(ConstRdataPtr source) {
+    s_Rdata* py_rdata =
+        static_cast<s_Rdata*>(rdata_type.tp_alloc(&rdata_type, 0));
+    if (py_rdata == NULL) {
+        isc_throw(PyCPPWrapperException, "Unexpected NULL C++ object, "
+                  "probably due to short memory");
+    }
+    py_rdata->cppobj = source;
+    return (py_rdata);
 }
+
+bool
+PyRdata_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &rdata_type));
+}
+
+const Rdata&
+PyRdata_ToRdata(const PyObject* rdata_obj) {
+    if (rdata_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in Rdata PyObject conversion");
+    }
+    const s_Rdata* rdata = static_cast<const s_Rdata*>(rdata_obj);
+    return (*rdata->cppobj);
+}
+
+} // end python namespace
+} // end dns namespace
+} // end isc namespace
diff --git a/src/lib/dns/python/rdata_python.h b/src/lib/dns/python/rdata_python.h
new file mode 100644
index 0000000..c7ddd57
--- /dev/null
+++ b/src/lib/dns/python/rdata_python.h
@@ -0,0 +1,68 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_RDATA_H
+#define __PYTHON_RDATA_H 1
+
+#include <Python.h>
+
+#include <dns/rdata.h>
+
+namespace isc {
+namespace dns {
+namespace python {
+
+extern PyObject* po_InvalidRdataLength;
+extern PyObject* po_InvalidRdataText;
+extern PyObject* po_CharStringTooLong;
+
+extern PyTypeObject rdata_type;
+
+/// This is a simple shortcut to create a python Rdata object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createRdataObject(isc::dns::rdata::ConstRdataPtr source);
+
+/// \brief Checks if the given python object is a Rdata object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type Rdata, false otherwise
+bool PyRdata_Check(PyObject* obj);
+
+/// \brief Returns a reference to the Rdata object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type Rdata; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRdata_Check()
+///
+/// \note This is not a copy; if the Rdata is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rdata_obj The rdata object to convert
+const isc::dns::rdata::Rdata& PyRdata_ToRdata(const PyObject* rdata_obj);
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_RDATA_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/rrclass_python.cc b/src/lib/dns/python/rrclass_python.cc
index 6d150c2..0014187 100644
--- a/src/lib/dns/python/rrclass_python.cc
+++ b/src/lib/dns/python/rrclass_python.cc
@@ -11,35 +11,28 @@
 // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
+#include <Python.h>
 
 #include <dns/rrclass.h>
-using namespace isc::dns;
-using namespace isc::util;
-
-//
-// 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
-//
+#include <dns/messagerenderer.h>
+#include <util/buffer.h>
+#include <util/python/pycppwrapper_util.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
+#include "rrclass_python.h"
+#include "messagerenderer_python.h"
+#include "pydnspp_common.h"
 
-//
-// RRClass
-//
 
+using namespace isc::dns;
+using namespace isc::dns::python;
+using namespace isc::util;
+using namespace isc::util::python;
+namespace {
 // The s_* Class simply covers one instantiation of the object
 class s_RRClass : public PyObject {
 public:
-    RRClass* rrclass;
+    s_RRClass() : cppobj(NULL) {};
+    RRClass* cppobj;
 };
 
 //
@@ -48,25 +41,26 @@ public:
 //
 
 // General creation and destruction
-static int RRClass_init(s_RRClass* self, PyObject* args);
-static void RRClass_destroy(s_RRClass* self);
+int RRClass_init(s_RRClass* self, PyObject* args);
+void RRClass_destroy(s_RRClass* self);
 
 // These are the functions we export
-static PyObject* RRClass_toText(s_RRClass* self);
+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);
+PyObject* RRClass_str(PyObject* self);
+PyObject* RRClass_toWire(s_RRClass* self, PyObject* args);
+PyObject* RRClass_getCode(s_RRClass* self);
+PyObject* RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op);
 
 // Static function for direct class creation
-static PyObject* RRClass_IN(s_RRClass *self);
-static PyObject* RRClass_CH(s_RRClass *self);
-static PyObject* RRClass_HS(s_RRClass *self);
-static PyObject* RRClass_NONE(s_RRClass *self);
-static PyObject* RRClass_ANY(s_RRClass *self);
+PyObject* RRClass_IN(s_RRClass *self);
+PyObject* RRClass_CH(s_RRClass *self);
+PyObject* RRClass_HS(s_RRClass *self);
+PyObject* RRClass_NONE(s_RRClass *self);
+PyObject* RRClass_ANY(s_RRClass *self);
 
+typedef CPPPyObjectContainer<s_RRClass, RRClass> RRClassContainer;
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -74,7 +68,7 @@ static PyObject* RRClass_ANY(s_RRClass *self);
 // 2. Our static function here
 // 3. Argument type
 // 4. Documentation
-static PyMethodDef RRClass_methods[] = {
+PyMethodDef RRClass_methods[] = {
     { "to_text", reinterpret_cast<PyCFunction>(RRClass_toText), METH_NOARGS,
       "Returns the string representation" },
     { "to_wire", reinterpret_cast<PyCFunction>(RRClass_toWire), METH_VARARGS,
@@ -94,63 +88,7 @@ static PyMethodDef RRClass_methods[] = {
     { 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)
-    "pydnspp.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
-    "The RRClass class encapsulates DNS resource record classes.\n"
-    "This class manages the 16-bit integer class codes in quite a straightforward"
-    "way.  The only non trivial task is to handle textual representations of"
-    "RR classes, such as \"IN\", \"CH\", or \"CLASS65534\".",
-    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
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
-static int
+int
 RRClass_init(s_RRClass* self, PyObject* args) {
     const char* s;
     long i;
@@ -164,7 +102,7 @@ RRClass_init(s_RRClass* self, PyObject* args) {
     // (the way to do exceptions is to set PyErr and return -1)
     try {
         if (PyArg_ParseTuple(args, "s", &s)) {
-            self->rrclass = new RRClass(s);
+            self->cppobj = new RRClass(s);
             return (0);
         } else if (PyArg_ParseTuple(args, "l", &i)) {
             if (i < 0 || i > 0xffff) {
@@ -173,7 +111,7 @@ RRClass_init(s_RRClass* self, PyObject* args) {
                                 "RR class number out of range");
                 return (-1);
             }
-            self->rrclass = new RRClass(i);
+            self->cppobj = new RRClass(i);
             return (0);
         } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
             uint8_t data[2];
@@ -182,7 +120,7 @@ RRClass_init(s_RRClass* self, PyObject* args) {
                 return (result);
             }
             InputBuffer ib(data, 2);
-            self->rrclass = new RRClass(ib);
+            self->cppobj = new RRClass(ib);
             PyErr_Clear();
             return (0);
         }
@@ -199,20 +137,20 @@ RRClass_init(s_RRClass* self, PyObject* args) {
     return (-1);
 }
 
-static void
+void
 RRClass_destroy(s_RRClass* self) {
-    delete self->rrclass;
-    self->rrclass = NULL;
+    delete self->cppobj;
+    self->cppobj = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
+PyObject*
 RRClass_toText(s_RRClass* self) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->rrclass->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
-static PyObject*
+PyObject*
 RRClass_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
@@ -220,16 +158,16 @@ RRClass_str(PyObject* self) {
                                 const_cast<char*>("")));
 }
 
-static PyObject*
+PyObject*
 RRClass_toWire(s_RRClass* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
-    
+    PyObject* mr;
+
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
-        
+
         OutputBuffer buffer(2);
-        self->rrclass->toWire(buffer);
+        self->cppobj->toWire(buffer);
         PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
         // We need to release the object we temporarily created here
@@ -237,7 +175,7 @@ RRClass_toWire(s_RRClass* self, PyObject* args) {
         Py_DECREF(n);
         return (result);
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-        self->rrclass->toWire(*mr->messagerenderer);
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
         // If we return NULL it is seen as an error, so use this for
         // None returns
         Py_RETURN_NONE;
@@ -248,12 +186,12 @@ RRClass_toWire(s_RRClass* self, PyObject* args) {
     return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRClass_getCode(s_RRClass* self) {
-    return (Py_BuildValue("I", self->rrclass->getCode()));
+    return (Py_BuildValue("I", self->cppobj->getCode()));
 }
 
-static PyObject* 
+PyObject*
 RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op) {
     bool c;
 
@@ -265,24 +203,24 @@ RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op) {
 
     switch (op) {
     case Py_LT:
-        c = *self->rrclass < *other->rrclass;
+        c = *self->cppobj < *other->cppobj;
         break;
     case Py_LE:
-        c = *self->rrclass < *other->rrclass ||
-            *self->rrclass == *other->rrclass;
+        c = *self->cppobj < *other->cppobj ||
+            *self->cppobj == *other->cppobj;
         break;
     case Py_EQ:
-        c = *self->rrclass == *other->rrclass;
+        c = *self->cppobj == *other->cppobj;
         break;
     case Py_NE:
-        c = *self->rrclass != *other->rrclass;
+        c = *self->cppobj != *other->cppobj;
         break;
     case Py_GT:
-        c = *other->rrclass < *self->rrclass;
+        c = *other->cppobj < *self->cppobj;
         break;
     case Py_GE:
-        c = *other->rrclass < *self->rrclass ||
-            *self->rrclass == *other->rrclass;
+        c = *other->cppobj < *self->cppobj ||
+            *self->cppobj == *other->cppobj;
         break;
     default:
         PyErr_SetString(PyExc_IndexError,
@@ -298,56 +236,131 @@ RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op) {
 //
 // Common function for RRClass_IN/CH/etc.
 //
-static PyObject* RRClass_createStatic(RRClass stc) {
+PyObject* RRClass_createStatic(RRClass stc) {
     s_RRClass* ret = PyObject_New(s_RRClass, &rrclass_type);
     if (ret != NULL) {
-        ret->rrclass = new RRClass(stc);
+        ret->cppobj = new RRClass(stc);
     }
     return (ret);
 }
 
-static PyObject* RRClass_IN(s_RRClass*) {
+PyObject* RRClass_IN(s_RRClass*) {
     return (RRClass_createStatic(RRClass::IN()));
 }
 
-static PyObject* RRClass_CH(s_RRClass*) {
+PyObject* RRClass_CH(s_RRClass*) {
     return (RRClass_createStatic(RRClass::CH()));
 }
 
-static PyObject* RRClass_HS(s_RRClass*) {
+PyObject* RRClass_HS(s_RRClass*) {
     return (RRClass_createStatic(RRClass::HS()));
 }
 
-static PyObject* RRClass_NONE(s_RRClass*) {
+PyObject* RRClass_NONE(s_RRClass*) {
     return (RRClass_createStatic(RRClass::NONE()));
 }
 
-static PyObject* RRClass_ANY(s_RRClass*) {
+PyObject* RRClass_ANY(s_RRClass*) {
     return (RRClass_createStatic(RRClass::ANY()));
 }
-// end of RRClass
+
+} // end anonymous namespace
+
+namespace isc {
+namespace dns {
+namespace python {
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function in pydnspp.cc
+//
+PyObject* po_InvalidRRClass;
+PyObject* po_IncompleteRRClass;
+
+
+// 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.
+PyTypeObject rrclass_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.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
+    "The RRClass class encapsulates DNS resource record classes.\n"
+    "This class manages the 16-bit integer class codes in quite a straightforward"
+    "way.  The only non trivial task is to handle textual representations of"
+    "RR classes, such as \"IN\", \"CH\", or \"CLASS65534\".",
+    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
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+PyObject*
+createRRClassObject(const RRClass& source) {
+    RRClassContainer container(PyObject_New(s_RRClass, &rrclass_type));
+    container.set(new RRClass(source));
+    return (container.release());
+}
 
 
-// Module Initialization, all statics are initialized here
 bool
-initModulePart_RRClass(PyObject* mod) {
-    // Add the exceptions to the module
-    po_InvalidRRClass = PyErr_NewException("pydnspp.InvalidRRClass", NULL, NULL);
-    Py_INCREF(po_InvalidRRClass);
-    PyModule_AddObject(mod, "InvalidRRClass", po_InvalidRRClass);
-    po_IncompleteRRClass = PyErr_NewException("pydnspp.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);
+PyRRClass_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
-    Py_INCREF(&rrclass_type);
-    PyModule_AddObject(mod, "RRClass",
-                       reinterpret_cast<PyObject*>(&rrclass_type));
-    
-    return (true);
+    return (PyObject_TypeCheck(obj, &rrclass_type));
 }
+
+const RRClass&
+PyRRClass_ToRRClass(const PyObject* rrclass_obj) {
+    if (rrclass_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in RRClass PyObject conversion");
+    }
+    const s_RRClass* rrclass = static_cast<const s_RRClass*>(rrclass_obj);
+    return (*rrclass->cppobj);
+}
+
+} // end namespace python
+} // end namespace dns
+} // end namespace isc
diff --git a/src/lib/dns/python/rrclass_python.h b/src/lib/dns/python/rrclass_python.h
new file mode 100644
index 0000000..f58bba6
--- /dev/null
+++ b/src/lib/dns/python/rrclass_python.h
@@ -0,0 +1,68 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_RRCLASS_H
+#define __PYTHON_RRCLASS_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class RRClass;
+
+namespace python {
+
+extern PyObject* po_InvalidRRClass;
+extern PyObject* po_IncompleteRRClass;
+
+extern PyTypeObject rrclass_type;
+
+/// This is a simple shortcut to create a python RRClass object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createRRClassObject(const RRClass& source);
+
+/// \brief Checks if the given python object is a RRClass object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type RRClass, false otherwise
+bool PyRRClass_Check(PyObject* obj);
+
+/// \brief Returns a reference to the RRClass object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type RRClass; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRRClass_Check()
+///
+/// \note This is not a copy; if the RRClass is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rrclass_obj The rrclass object to convert
+const RRClass& PyRRClass_ToRRClass(const PyObject* rrclass_obj);
+
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_RRCLASS_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/rrset_python.cc b/src/lib/dns/python/rrset_python.cc
index 71a0710..9fc3d79 100644
--- a/src/lib/dns/python/rrset_python.cc
+++ b/src/lib/dns/python/rrset_python.cc
@@ -12,55 +12,63 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <dns/rrset.h>
+#include <Python.h>
 
-//
-// Declaration of the custom exceptions
-// Initialization and addition of these go in the module init at the
-// end
-//
-static PyObject* po_EmptyRRset;
+#include <util/python/pycppwrapper_util.h>
 
-//
-// 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
+#include <dns/rrset.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+
+#include "name_python.h"
+#include "pydnspp_common.h"
+#include "rrset_python.h"
+#include "rrclass_python.h"
+#include "rrtype_python.h"
+#include "rrttl_python.h"
+#include "rdata_python.h"
+#include "messagerenderer_python.h"
+
+using namespace std;
 using namespace isc::dns;
+using namespace isc::dns::python;
 using namespace isc::util;
+using namespace isc::util::python;
+
+namespace {
 
-// RRset
+// The s_* Class simply coverst one instantiation of the object
 
 // Using a shared_ptr here should not really be necessary (PyObject
 // is already reference-counted), however internally on the cpp side,
 // not doing so might result in problems, since we can't copy construct
-// rrsets, adding them to messages results in a problem when the
-// message is destroyed or cleared later
+// rdata field, adding them to rrsets results in a problem when the
+// rrset is destroyed later
 class s_RRset : public PyObject {
 public:
-    RRsetPtr rrset;
+    isc::dns::RRsetPtr cppobj;
 };
 
-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_str(PyObject* self);
-static PyObject* RRset_toWire(s_RRset* self, PyObject* args);
-static PyObject* RRset_addRdata(s_RRset* self, PyObject* args);
-static PyObject* RRset_getRdata(s_RRset* self);
+int RRset_init(s_RRset* self, PyObject* args);
+void RRset_destroy(s_RRset* self);
+
+PyObject* RRset_getRdataCount(s_RRset* self);
+PyObject* RRset_getName(s_RRset* self);
+PyObject* RRset_getClass(s_RRset* self);
+PyObject* RRset_getType(s_RRset* self);
+PyObject* RRset_getTTL(s_RRset* self);
+PyObject* RRset_setName(s_RRset* self, PyObject* args);
+PyObject* RRset_setTTL(s_RRset* self, PyObject* args);
+PyObject* RRset_toText(s_RRset* self);
+PyObject* RRset_str(PyObject* self);
+PyObject* RRset_toWire(s_RRset* self, PyObject* args);
+PyObject* RRset_addRdata(s_RRset* self, PyObject* args);
+PyObject* RRset_getRdata(s_RRset* self);
+PyObject* RRset_removeRRsig(s_RRset* self);
+
 // TODO: iterator?
 
-static PyMethodDef RRset_methods[] = {
+PyMethodDef RRset_methods[] = {
     { "get_rdata_count", reinterpret_cast<PyCFunction>(RRset_getRdataCount), METH_NOARGS,
       "Returns the number of rdata fields." },
     { "get_name", reinterpret_cast<PyCFunction>(RRset_getName), METH_NOARGS,
@@ -88,208 +96,142 @@ static PyMethodDef RRset_methods[] = {
       "Adds the rdata for one RR to the RRset.\nTakes an Rdata object as an argument" },
     { "get_rdata", reinterpret_cast<PyCFunction>(RRset_getRdata), METH_NOARGS,
       "Returns a List containing all Rdata elements" },
+    { "remove_rrsig", reinterpret_cast<PyCFunction>(RRset_removeRRsig), METH_NOARGS,
+      "Clears the list of RRsigs for this RRset" },
     { NULL, NULL, 0, NULL }
 };
 
-static PyTypeObject rrset_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "pydnspp.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
-    RRset_str,                          // tp_str
-    NULL,                               // tp_getattro
-    NULL,                               // tp_setattro
-    NULL,                               // tp_as_buffer
-    Py_TPFLAGS_DEFAULT,                 // tp_flags
-    "The AbstractRRset class is an abstract base class that "
-    "models a DNS RRset.\n\n"
-    "An object of (a specific derived class of) AbstractRRset "
-    "models an RRset as described in the DNS standard:\n"
-    "A set of DNS resource records (RRs) of the same type and class. "
-    "The standard requires the TTL of all RRs in an RRset be the same; "
-    "this class follows that requirement.\n\n"
-    "Note about duplicate RDATA: RFC2181 states that it's meaningless that an "
-    "RRset contains two identical RRs and that name servers should suppress "
-    "such duplicates.\n"
-    "This class is not responsible for ensuring this requirement: For example, "
-    "addRdata() method doesn't check if there's already RDATA identical "
-    "to the one being added.\n"
-    "This is because such checks can be expensive, and it's often easy to "
-    "ensure the uniqueness requirement at the %data preparation phase "
-    "(e.g. when loading a zone).",
-    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
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
-static int
+int
 RRset_init(s_RRset* self, PyObject* args) {
-    s_Name* name;
-    s_RRClass* rrclass;
-    s_RRType* rrtype;
-    s_RRTTL* rrttl;
+    PyObject* name;
+    PyObject* rrclass;
+    PyObject* rrtype;
+    PyObject* rrttl;
 
     if (PyArg_ParseTuple(args, "O!O!O!O!", &name_type, &name,
                                            &rrclass_type, &rrclass,
                                            &rrtype_type, &rrtype,
                                            &rrttl_type, &rrttl
        )) {
-        self->rrset = RRsetPtr(new RRset(*name->cppobj, *rrclass->rrclass,
-                                *rrtype->rrtype, *rrttl->rrttl));
+        self->cppobj = RRsetPtr(new RRset(PyName_ToName(name),
+                                          PyRRClass_ToRRClass(rrclass),
+                                          PyRRType_ToRRType(rrtype),
+                                          PyRRTTL_ToRRTTL(rrttl)));
         return (0);
     }
 
-    self->rrset = RRsetPtr();
+    self->cppobj = RRsetPtr();
     return (-1);
 }
 
-static void
+void
 RRset_destroy(s_RRset* self) {
     // Clear the shared_ptr so that its reference count is zero
     // before we call tp_free() (there is no direct release())
-    self->rrset.reset();
+    self->cppobj.reset();
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
+PyObject*
 RRset_getRdataCount(s_RRset* self) {
-    return (Py_BuildValue("I", self->rrset->getRdataCount()));
+    return (Py_BuildValue("I", self->cppobj->getRdataCount()));
 }
 
-static PyObject*
+PyObject*
 RRset_getName(s_RRset* self) {
-    s_Name* name;
-
-    // is this the best way to do this?
-    name = static_cast<s_Name*>(name_type.tp_alloc(&name_type, 0));
-    if (name != NULL) {
-        name->cppobj = new Name(self->rrset->getName());
-        if (name->cppobj == NULL)
-          {
-            Py_DECREF(name);
-            return (NULL);
-          }
+    try {
+        return (createNameObject(self->cppobj->getName()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting rrset Name: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting rrset Name");
     }
-
-    return (name);
+    return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRset_getClass(s_RRset* self) {
-    s_RRClass* rrclass;
-
-    rrclass = static_cast<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);
-          }
+    try {
+        return (createRRClassObject(self->cppobj->getClass()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting question RRClass: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting question RRClass");
     }
-
-    return (rrclass);
+    return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRset_getType(s_RRset* self) {
-    s_RRType* rrtype;
-
-    rrtype = static_cast<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);
-          }
+    try {
+        return (createRRTypeObject(self->cppobj->getType()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting question RRType: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting question RRType");
     }
-
-    return (rrtype);
+    return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRset_getTTL(s_RRset* self) {
-    s_RRTTL* rrttl;
-
-    rrttl = static_cast<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);
-          }
+    try {
+        return (createRRTTLObject(self->cppobj->getTTL()));
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting question TTL: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting question TTL");
     }
-
-    return (rrttl);
+    return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRset_setName(s_RRset* self, PyObject* args) {
-    s_Name* name;
+    PyObject* name;
     if (!PyArg_ParseTuple(args, "O!", &name_type, &name)) {
         return (NULL);
     }
-    self->rrset->setName(*name->cppobj);
+    self->cppobj->setName(PyName_ToName(name));
     Py_RETURN_NONE;
 }
 
-static PyObject*
+PyObject*
 RRset_setTTL(s_RRset* self, PyObject* args) {
-    s_RRTTL* rrttl;
+    PyObject* rrttl;
     if (!PyArg_ParseTuple(args, "O!", &rrttl_type, &rrttl)) {
         return (NULL);
     }
-    self->rrset->setTTL(*rrttl->rrttl);
+    self->cppobj->setTTL(PyRRTTL_ToRRTTL(rrttl));
     Py_RETURN_NONE;
 }
 
-static PyObject*
+PyObject*
 RRset_toText(s_RRset* self) {
     try {
-        return (Py_BuildValue("s", self->rrset->toText().c_str()));
+        return (Py_BuildValue("s", self->cppobj->toText().c_str()));
     } catch (const EmptyRRset& ers) {
         PyErr_SetString(po_EmptyRRset, ers.what());
         return (NULL);
     }
 }
 
-static PyObject*
+PyObject*
 RRset_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
@@ -297,17 +239,17 @@ RRset_str(PyObject* self) {
                                 const_cast<char*>("")));
 }
 
-static PyObject*
+PyObject*
 RRset_toWire(s_RRset* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
+    PyObject* mr;
 
     try {
         if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
             PyObject* bytes_o = bytes;
-            
+
             OutputBuffer buffer(4096);
-            self->rrset->toWire(buffer);
+            self->cppobj->toWire(buffer);
             PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
             PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
             // We need to release the object we temporarily created here
@@ -315,7 +257,7 @@ RRset_toWire(s_RRset* self, PyObject* args) {
             Py_DECREF(n);
             return (result);
         } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-            self->rrset->toWire(*mr->messagerenderer);
+            self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
             // If we return NULL it is seen as an error, so use this for
             // None returns
             Py_RETURN_NONE;
@@ -331,14 +273,14 @@ RRset_toWire(s_RRset* self, PyObject* args) {
     return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRset_addRdata(s_RRset* self, PyObject* args) {
-    s_Rdata* rdata;
+    PyObject* rdata;
     if (!PyArg_ParseTuple(args, "O!", &rdata_type, &rdata)) {
         return (NULL);
     }
     try {
-        self->rrset->addRdata(*rdata->rdata);
+        self->cppobj->addRdata(PyRdata_ToRdata(rdata));
         Py_RETURN_NONE;
     } catch (const std::bad_cast&) {
         PyErr_Clear();
@@ -348,55 +290,173 @@ RRset_addRdata(s_RRset* self, PyObject* args) {
     }
 }
 
-static PyObject*
+PyObject*
 RRset_getRdata(s_RRset* self) {
     PyObject* list = PyList_New(0);
 
-    RdataIteratorPtr it = self->rrset->getRdataIterator();
-
-    for (; !it->isLast(); it->next()) {
-        s_Rdata *rds = static_cast<s_Rdata*>(rdata_type.tp_alloc(&rdata_type, 0));
-        if (rds != NULL) {
-            // hmz them iterators/shared_ptrs and private constructors
-            // make this a bit weird, so we create a new one with
-            // the data available
-            const Rdata *rd = &it->getCurrent();
-            rds->rdata = createRdata(self->rrset->getType(), self->rrset->getClass(), *rd);
-            PyList_Append(list, rds);
-        } else {
-            return (NULL);
+    RdataIteratorPtr it = self->cppobj->getRdataIterator();
+
+    try {
+        for (; !it->isLast(); it->next()) {
+            const rdata::Rdata *rd = &it->getCurrent();
+            if (PyList_Append(list,
+                    createRdataObject(createRdata(self->cppobj->getType(),
+                                      self->cppobj->getClass(), *rd))) == -1) {
+                Py_DECREF(list);
+                return (NULL);
+            }
         }
+        return (list);
+    } catch (const exception& ex) {
+        const string ex_what =
+            "Unexpected failure getting rrset Rdata: " +
+            string(ex.what());
+        PyErr_SetString(po_IscException, ex_what.c_str());
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure getting rrset Rdata");
     }
-    
-    return (list);
+    Py_DECREF(list);
+    return (NULL);
 }
 
-// end of RRset
+PyObject*
+RRset_removeRRsig(s_RRset* self) {
+    self->cppobj->removeRRsig();
+    Py_RETURN_NONE;
+}
 
+} // end of unnamed namespace
 
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_RRset(PyObject* mod) {
-    // Add the exceptions to the module
-    po_EmptyRRset = PyErr_NewException("pydnspp.EmptyRRset", NULL, NULL);
-    PyModule_AddObject(mod, "EmptyRRset", po_EmptyRRset);
+namespace isc {
+namespace dns {
+namespace python {
 
-    // Add the enums to the module
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the module init at the
+// end
+//
+PyObject* po_EmptyRRset;
 
-    // Add the constants to the module
+PyTypeObject rrset_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.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
+    RRset_str,                          // tp_str
+    NULL,                               // tp_getattro
+    NULL,                               // tp_setattro
+    NULL,                               // tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                 // tp_flags
+    "The AbstractRRset class is an abstract base class that "
+    "models a DNS RRset.\n\n"
+    "An object of (a specific derived class of) AbstractRRset "
+    "models an RRset as described in the DNS standard:\n"
+    "A set of DNS resource records (RRs) of the same type and class. "
+    "The standard requires the TTL of all RRs in an RRset be the same; "
+    "this class follows that requirement.\n\n"
+    "Note about duplicate RDATA: RFC2181 states that it's meaningless that an "
+    "RRset contains two identical RRs and that name servers should suppress "
+    "such duplicates.\n"
+    "This class is not responsible for ensuring this requirement: For example, "
+    "addRdata() method doesn't check if there's already RDATA identical "
+    "to the one being added.\n"
+    "This is because such checks can be expensive, and it's often easy to "
+    "ensure the uniqueness requirement at the %data preparation phase "
+    "(e.g. when loading a zone).",
+    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
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+PyObject*
+createRRsetObject(const RRset& source) {
 
-    // Add the classes to the module
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module
+    // RRsets are noncopyable, so as a workaround we recreate a new one
+    // and copy over all content
+    RRsetPtr new_rrset = isc::dns::RRsetPtr(
+        new isc::dns::RRset(source.getName(), source.getClass(),
+                            source.getType(), source.getTTL()));
 
-    // NameComparisonResult
-    if (PyType_Ready(&rrset_type) < 0) {
-        return (false);
+    isc::dns::RdataIteratorPtr rdata_it(source.getRdataIterator());
+    for (rdata_it->first(); !rdata_it->isLast(); rdata_it->next()) {
+        new_rrset->addRdata(rdata_it->getCurrent());
+    }
+
+    isc::dns::RRsetPtr sigs = source.getRRsig();
+    if (sigs) {
+        new_rrset->addRRsig(sigs);
+    }
+    s_RRset* py_rrset =
+        static_cast<s_RRset*>(rrset_type.tp_alloc(&rrset_type, 0));
+    if (py_rrset == NULL) {
+        isc_throw(PyCPPWrapperException, "Unexpected NULL C++ object, "
+                  "probably due to short memory");
     }
-    Py_INCREF(&rrset_type);
-    PyModule_AddObject(mod, "RRset",
-                       reinterpret_cast<PyObject*>(&rrset_type));
-    
-    return (true);
+    py_rrset->cppobj = new_rrset;
+    return (py_rrset);
 }
 
+bool
+PyRRset_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &rrset_type));
+}
+
+RRset&
+PyRRset_ToRRset(PyObject* rrset_obj) {
+    s_RRset* rrset = static_cast<s_RRset*>(rrset_obj);
+    return (*rrset->cppobj);
+}
+
+RRsetPtr
+PyRRset_ToRRsetPtr(PyObject* rrset_obj) {
+    if (rrset_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in RRset PyObject conversion");
+    }
+    s_RRset* rrset = static_cast<s_RRset*>(rrset_obj);
+    return (rrset->cppobj);
+}
+
+
+} // end python namespace
+} // end dns namespace
+} // end isc namespace
diff --git a/src/lib/dns/python/rrset_python.h b/src/lib/dns/python/rrset_python.h
new file mode 100644
index 0000000..4268678
--- /dev/null
+++ b/src/lib/dns/python/rrset_python.h
@@ -0,0 +1,78 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_RRSET_H
+#define __PYTHON_RRSET_H 1
+
+#include <Python.h>
+
+#include <dns/rrset.h>
+
+#include <util/python/pycppwrapper_util.h>
+
+namespace isc {
+namespace dns {
+namespace python {
+
+extern PyObject* po_EmptyRRset;
+
+extern PyTypeObject rrset_type;
+
+/// This is a simple shortcut to create a python RRset object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createRRsetObject(const RRset& source);
+
+/// \brief Checks if the given python object is a RRset object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type RRset, false otherwise
+bool PyRRset_Check(PyObject* obj);
+
+/// \brief Returns a reference to the RRset object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type RRset; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRRset_Check()
+///
+/// \note This is not a copy; if the RRset is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rrset_obj The rrset object to convert
+RRset& PyRRset_ToRRset(PyObject* rrset_obj);
+
+/// \brief Returns the shared_ptr of the RRset object contained within the
+///        given Python object.
+///
+/// \note The given object MUST be of type RRset; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRRset_Check()
+///
+/// \param rrset_obj The rrset object to convert
+RRsetPtr PyRRset_ToRRsetPtr(PyObject* rrset_obj);
+
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_RRSET_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/rrttl_python.cc b/src/lib/dns/python/rrttl_python.cc
index c4b25bf..3a3f067 100644
--- a/src/lib/dns/python/rrttl_python.cc
+++ b/src/lib/dns/python/rrttl_python.cc
@@ -12,57 +12,41 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <Python.h>
 #include <vector>
 
 #include <dns/rrttl.h>
+#include <dns/messagerenderer.h>
+#include <util/buffer.h>
+#include <util/python/pycppwrapper_util.h>
+
+#include "rrttl_python.h"
+#include "pydnspp_common.h"
+#include "messagerenderer_python.h"
 
 using namespace std;
 using namespace isc::dns;
+using namespace isc::dns::python;
 using namespace isc::util;
+using namespace isc::util::python;
 
-//
-// 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
-//
-
+namespace {
 // The s_* Class simply covers one instantiation of the object
 class s_RRTTL : public PyObject {
 public:
-    RRTTL* rrttl;
+    s_RRTTL() : cppobj(NULL) {};
+    isc::dns::RRTTL* cppobj;
 };
 
-//
-// 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);
+typedef CPPPyObjectContainer<s_RRTTL, RRTTL> RRTTLContainer;
 
-// These are the functions we export
-static PyObject* RRTTL_toText(s_RRTTL* self);
+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);
+PyObject* RRTTL_str(PyObject* self);
+PyObject* RRTTL_toWire(s_RRTTL* self, PyObject* args);
+PyObject* RRTTL_getValue(s_RRTTL* self);
+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
@@ -70,7 +54,7 @@ static PyObject* RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op);
 // 2. Our static function here
 // 3. Argument type
 // 4. Documentation
-static PyMethodDef RRTTL_methods[] = {
+PyMethodDef RRTTL_methods[] = {
     { "to_text", reinterpret_cast<PyCFunction>(RRTTL_toText), METH_NOARGS,
       "Returns the string representation" },
     { "to_wire", reinterpret_cast<PyCFunction>(RRTTL_toWire), METH_VARARGS,
@@ -85,65 +69,7 @@ static PyMethodDef RRTTL_methods[] = {
     { 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)
-    "pydnspp.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
-    "The RRTTL class encapsulates TTLs used in DNS resource records.\n\n"
-    "This is a straightforward class; an RRTTL object simply maintains a "
-    "32-bit unsigned integer corresponding to the TTL value.  The main purpose "
-    "of this class is to provide convenient interfaces to convert a textual "
-    "representation into the integer TTL value and vice versa, and to handle "
-    "wire-format representations.",
-    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
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
-static int
+int
 RRTTL_init(s_RRTTL* self, PyObject* args) {
     const char* s;
     long long i;
@@ -157,7 +83,7 @@ RRTTL_init(s_RRTTL* self, PyObject* args) {
     // (the way to do exceptions is to set PyErr and return -1)
     try {
         if (PyArg_ParseTuple(args, "s", &s)) {
-            self->rrttl = new RRTTL(s);
+            self->cppobj = new RRTTL(s);
             return (0);
         } else if (PyArg_ParseTuple(args, "L", &i)) {
             PyErr_Clear();
@@ -165,7 +91,7 @@ RRTTL_init(s_RRTTL* self, PyObject* args) {
                 PyErr_SetString(PyExc_ValueError, "RR TTL number out of range");
                 return (-1);
             }
-            self->rrttl = new RRTTL(i);
+            self->cppobj = new RRTTL(i);
             return (0);
         } else if (PyArg_ParseTuple(args, "O", &bytes) &&
                    PySequence_Check(bytes)) {
@@ -176,7 +102,7 @@ RRTTL_init(s_RRTTL* self, PyObject* args) {
                 return (result);
             }
             InputBuffer ib(&data[0], size);
-            self->rrttl = new RRTTL(ib);
+            self->cppobj = new RRTTL(ib);
             PyErr_Clear();
             return (0);
         }
@@ -200,20 +126,20 @@ RRTTL_init(s_RRTTL* self, PyObject* args) {
     return (-1);
 }
 
-static void
+void
 RRTTL_destroy(s_RRTTL* self) {
-    delete self->rrttl;
-    self->rrttl = NULL;
+    delete self->cppobj;
+    self->cppobj = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
+PyObject*
 RRTTL_toText(s_RRTTL* self) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->rrttl->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
-static PyObject*
+PyObject*
 RRTTL_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self,
@@ -221,16 +147,16 @@ RRTTL_str(PyObject* self) {
                                 const_cast<char*>("")));
 }
 
-static PyObject*
+PyObject*
 RRTTL_toWire(s_RRTTL* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
-    
+    PyObject* mr;
+
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
-        
+
         OutputBuffer buffer(4);
-        self->rrttl->toWire(buffer);
+        self->cppobj->toWire(buffer);
         PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()),
                                                 buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
@@ -239,7 +165,7 @@ RRTTL_toWire(s_RRTTL* self, PyObject* args) {
         Py_DECREF(n);
         return (result);
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-        self->rrttl->toWire(*mr->messagerenderer);
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
         // If we return NULL it is seen as an error, so use this for
         // None returns
         Py_RETURN_NONE;
@@ -250,12 +176,12 @@ RRTTL_toWire(s_RRTTL* self, PyObject* args) {
     return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRTTL_getValue(s_RRTTL* self) {
-    return (Py_BuildValue("I", self->rrttl->getValue()));
+    return (Py_BuildValue("I", self->cppobj->getValue()));
 }
 
-static PyObject* 
+PyObject*
 RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op) {
     bool c = false;
 
@@ -267,24 +193,24 @@ RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op) {
 
     switch (op) {
     case Py_LT:
-        c = *self->rrttl < *other->rrttl;
+        c = *self->cppobj < *other->cppobj;
         break;
     case Py_LE:
-        c = *self->rrttl < *other->rrttl ||
-            *self->rrttl == *other->rrttl;
+        c = *self->cppobj < *other->cppobj ||
+            *self->cppobj == *other->cppobj;
         break;
     case Py_EQ:
-        c = *self->rrttl == *other->rrttl;
+        c = *self->cppobj == *other->cppobj;
         break;
     case Py_NE:
-        c = *self->rrttl != *other->rrttl;
+        c = *self->cppobj != *other->cppobj;
         break;
     case Py_GT:
-        c = *other->rrttl < *self->rrttl;
+        c = *other->cppobj < *self->cppobj;
         break;
     case Py_GE:
-        c = *other->rrttl < *self->rrttl ||
-            *self->rrttl == *other->rrttl;
+        c = *other->cppobj < *self->cppobj ||
+            *self->cppobj == *other->cppobj;
         break;
     }
     if (c)
@@ -292,27 +218,104 @@ RRTTL_richcmp(s_RRTTL* self, s_RRTTL* other, int op) {
     else
         Py_RETURN_FALSE;
 }
-// end of RRTTL
 
+} // end anonymous namespace
+
+namespace isc {
+namespace dns {
+namespace python {
+
+//
+// Declaration of the custom exceptions
+// Initialization and addition of these go in the initModulePart
+// function in pydnspp.cc
+//
+PyObject* po_InvalidRRTTL;
+PyObject* po_IncompleteRRTTL;
+
+// 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.
+PyTypeObject rrttl_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.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
+    "The RRTTL class encapsulates TTLs used in DNS resource records.\n\n"
+    "This is a straightforward class; an RRTTL object simply maintains a "
+    "32-bit unsigned integer corresponding to the TTL value.  The main purpose "
+    "of this class is to provide convenient interfaces to convert a textual "
+    "representation into the integer TTL value and vice versa, and to handle "
+    "wire-format representations.",
+    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
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
+
+PyObject*
+createRRTTLObject(const RRTTL& source) {
+    RRTTLContainer container(PyObject_New(s_RRTTL, &rrttl_type));
+    container.set(new RRTTL(source));
+    return (container.release());
+}
 
-// Module Initialization, all statics are initialized here
 bool
-initModulePart_RRTTL(PyObject* mod) {
-    // Add the exceptions to the module
-    po_InvalidRRTTL = PyErr_NewException("pydnspp.InvalidRRTTL", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidRRTTL", po_InvalidRRTTL);
-    po_IncompleteRRTTL = PyErr_NewException("pydnspp.IncompleteRRTTL", NULL, NULL);
-    PyModule_AddObject(mod, "IncompleteRRTTL", po_IncompleteRRTTL);
+PyRRTTL_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &rrttl_type));
+}
 
-    // 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);
+const RRTTL&
+PyRRTTL_ToRRTTL(const PyObject* rrttl_obj) {
+    if (rrttl_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in RRTTL PyObject conversion");
     }
-    Py_INCREF(&rrttl_type);
-    PyModule_AddObject(mod, "RRTTL",
-                       reinterpret_cast<PyObject*>(&rrttl_type));
-    
-    return (true);
+    const s_RRTTL* rrttl = static_cast<const s_RRTTL*>(rrttl_obj);
+    return (*rrttl->cppobj);
 }
+
+} // namespace python
+} // namespace dns
+} // namespace isc
diff --git a/src/lib/dns/python/rrttl_python.h b/src/lib/dns/python/rrttl_python.h
new file mode 100644
index 0000000..9dbc982
--- /dev/null
+++ b/src/lib/dns/python/rrttl_python.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_RRTTL_H
+#define __PYTHON_RRTTL_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class RRTTL;
+
+namespace python {
+
+extern PyObject* po_InvalidRRTTL;
+extern PyObject* po_IncompleteRRTTL;
+
+extern PyTypeObject rrttl_type;
+
+/// This is a simple shortcut to create a python RRTTL object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createRRTTLObject(const RRTTL& source);
+
+/// \brief Checks if the given python object is a RRTTL object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type RRTTL, false otherwise
+bool PyRRTTL_Check(PyObject* obj);
+
+/// \brief Returns a reference to the RRTTL object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type RRTTL; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRRTTL_Check()
+///
+/// \note This is not a copy; if the RRTTL is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rrttl_obj The rrttl object to convert
+const RRTTL& PyRRTTL_ToRRTTL(const PyObject* rrttl_obj);
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_RRTTL_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/rrtype_python.cc b/src/lib/dns/python/rrtype_python.cc
index 00e0acd..bf20b7c 100644
--- a/src/lib/dns/python/rrtype_python.cc
+++ b/src/lib/dns/python/rrtype_python.cc
@@ -12,77 +12,64 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <Python.h>
 #include <vector>
 
 #include <dns/rrtype.h>
+#include <dns/messagerenderer.h>
+#include <util/python/pycppwrapper_util.h>
+
+#include "rrtype_python.h"
+#include "messagerenderer_python.h"
+#include "pydnspp_common.h"
 
 using namespace std;
 using namespace isc::dns;
+using namespace isc::dns::python;
 using namespace isc::util;
+using namespace isc::util::python;
 
-//
-// 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
-//
-
+namespace {
 // The s_* Class simply covers one instantiation of the object
 class s_RRType : public PyObject {
 public:
-    const RRType* rrtype;
+    const RRType* cppobj;
 };
 
-//
-// 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);
+int RRType_init(s_RRType* self, PyObject* args);
+void RRType_destroy(s_RRType* self);
 
 // These are the functions we export
-static PyObject*
+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);
-static PyObject* RRType_NSEC3PARAM(s_RRType *self);
-static PyObject* RRType_DNAME(s_RRType *self);
-static PyObject* RRType_PTR(s_RRType *self);
-static PyObject* RRType_MX(s_RRType *self);
-static PyObject* RRType_DNSKEY(s_RRType *self);
-static PyObject* RRType_TXT(s_RRType *self);
-static PyObject* RRType_RRSIG(s_RRType *self);
-static PyObject* RRType_NSEC(s_RRType *self);
-static PyObject* RRType_AAAA(s_RRType *self);
-static PyObject* RRType_DS(s_RRType *self);
-static PyObject* RRType_OPT(s_RRType *self);
-static PyObject* RRType_A(s_RRType *self);
-static PyObject* RRType_NS(s_RRType *self);
-static PyObject* RRType_CNAME(s_RRType *self);
-static PyObject* RRType_SOA(s_RRType *self);
-static PyObject* RRType_NSEC3(s_RRType *self);
-static PyObject* RRType_IXFR(s_RRType *self);
-static PyObject* RRType_AXFR(s_RRType *self);
-static PyObject* RRType_ANY(s_RRType *self);
+PyObject* RRType_str(PyObject* self);
+PyObject* RRType_toWire(s_RRType* self, PyObject* args);
+PyObject* RRType_getCode(s_RRType* self);
+PyObject* RRType_richcmp(s_RRType* self, s_RRType* other, int op);
+PyObject* RRType_NSEC3PARAM(s_RRType *self);
+PyObject* RRType_DNAME(s_RRType *self);
+PyObject* RRType_PTR(s_RRType *self);
+PyObject* RRType_MX(s_RRType *self);
+PyObject* RRType_DNSKEY(s_RRType *self);
+PyObject* RRType_TXT(s_RRType *self);
+PyObject* RRType_RRSIG(s_RRType *self);
+PyObject* RRType_NSEC(s_RRType *self);
+PyObject* RRType_AAAA(s_RRType *self);
+PyObject* RRType_DS(s_RRType *self);
+PyObject* RRType_OPT(s_RRType *self);
+PyObject* RRType_A(s_RRType *self);
+PyObject* RRType_NS(s_RRType *self);
+PyObject* RRType_CNAME(s_RRType *self);
+PyObject* RRType_SOA(s_RRType *self);
+PyObject* RRType_NSEC3(s_RRType *self);
+PyObject* RRType_IXFR(s_RRType *self);
+PyObject* RRType_AXFR(s_RRType *self);
+PyObject* RRType_ANY(s_RRType *self);
+
+typedef CPPPyObjectContainer<s_RRType, RRType> RRTypeContainer;
 
 // This list contains the actual set of functions we have in
 // python. Each entry has
@@ -90,7 +77,7 @@ static PyObject* RRType_ANY(s_RRType *self);
 // 2. Our static function here
 // 3. Argument type
 // 4. Documentation
-static PyMethodDef RRType_methods[] = {
+PyMethodDef RRType_methods[] = {
     { "to_text", reinterpret_cast<PyCFunction>(RRType_toText), METH_NOARGS,
       "Returns the string representation" },
     { "to_wire", reinterpret_cast<PyCFunction>(RRType_toWire), METH_VARARGS,
@@ -124,63 +111,7 @@ static PyMethodDef RRType_methods[] = {
     { 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)
-    "pydnspp.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
-    "The RRType class encapsulates DNS resource record types.\n\n"
-    "This class manages the 16-bit integer type codes in quite a straightforward "
-    "way. The only non trivial task is to handle textual representations of "
-    "RR types, such as \"A\", \"AAAA\", or \"TYPE65534\".",
-    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
-    NULL,                               // tp_del
-    0                                   // tp_version_tag
-};
-
-static int
+int
 RRType_init(s_RRType* self, PyObject* args) {
     const char* s;
     long i;
@@ -194,7 +125,7 @@ RRType_init(s_RRType* self, PyObject* args) {
     // (the way to do exceptions is to set PyErr and return -1)
     try {
         if (PyArg_ParseTuple(args, "s", &s)) {
-            self->rrtype = new RRType(s);
+            self->cppobj = new RRType(s);
             return (0);
         } else if (PyArg_ParseTuple(args, "l", &i)) {
             PyErr_Clear();
@@ -202,7 +133,7 @@ RRType_init(s_RRType* self, PyObject* args) {
                 PyErr_SetString(PyExc_ValueError, "RR Type number out of range");
                 return (-1);
             }
-            self->rrtype = new RRType(i);
+            self->cppobj = new RRType(i);
             return (0);
         } else if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
             Py_ssize_t size = PySequence_Size(bytes);
@@ -212,7 +143,7 @@ RRType_init(s_RRType* self, PyObject* args) {
                 return (result);
             }
             InputBuffer ib(&data[0], size);
-            self->rrtype = new RRType(ib);
+            self->cppobj = new RRType(ib);
             PyErr_Clear();
             return (0);
         }
@@ -236,36 +167,36 @@ RRType_init(s_RRType* self, PyObject* args) {
     return (-1);
 }
 
-static void
+void
 RRType_destroy(s_RRType* self) {
-    delete self->rrtype;
-    self->rrtype = NULL;
+    delete self->cppobj;
+    self->cppobj = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 
-static PyObject*
+PyObject*
 RRType_toText(s_RRType* self) {
     // Py_BuildValue makes python objects from native data
-    return (Py_BuildValue("s", self->rrtype->toText().c_str()));
+    return (Py_BuildValue("s", self->cppobj->toText().c_str()));
 }
 
-static PyObject*
+PyObject*
 RRType_str(PyObject* self) {
     // Simply call the to_text method we already defined
     return (PyObject_CallMethod(self, const_cast<char*>("to_text"),
                                 const_cast<char*>("")));
 }
 
-static PyObject*
+PyObject*
 RRType_toWire(s_RRType* self, PyObject* args) {
     PyObject* bytes;
-    s_MessageRenderer* mr;
+    PyObject* mr;
 
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
 
         OutputBuffer buffer(2);
-        self->rrtype->toWire(buffer);
+        self->cppobj->toWire(buffer);
         PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
         // We need to release the object we temporarily created here
@@ -273,7 +204,7 @@ RRType_toWire(s_RRType* self, PyObject* args) {
         Py_DECREF(n);
         return (result);
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-        self->rrtype->toWire(*mr->messagerenderer);
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
         // If we return NULL it is seen as an error, so use this for
         // None returns
         Py_RETURN_NONE;
@@ -284,12 +215,12 @@ RRType_toWire(s_RRType* self, PyObject* args) {
     return (NULL);
 }
 
-static PyObject*
+PyObject*
 RRType_getCode(s_RRType* self) {
-    return (Py_BuildValue("I", self->rrtype->getCode()));
+    return (Py_BuildValue("I", self->cppobj->getCode()));
 }
 
-static PyObject* 
+PyObject*
 RRType_richcmp(s_RRType* self, s_RRType* other, int op) {
     bool c;
 
@@ -301,24 +232,24 @@ RRType_richcmp(s_RRType* self, s_RRType* other, int op) {
 
     switch (op) {
     case Py_LT:
-        c = *self->rrtype < *other->rrtype;
+        c = *self->cppobj < *other->cppobj;
         break;
     case Py_LE:
-        c = *self->rrtype < *other->rrtype ||
-            *self->rrtype == *other->rrtype;
+        c = *self->cppobj < *other->cppobj ||
+            *self->cppobj == *other->cppobj;
         break;
     case Py_EQ:
-        c = *self->rrtype == *other->rrtype;
+        c = *self->cppobj == *other->cppobj;
         break;
     case Py_NE:
-        c = *self->rrtype != *other->rrtype;
+        c = *self->cppobj != *other->cppobj;
         break;
     case Py_GT:
-        c = *other->rrtype < *self->rrtype;
+        c = *other->cppobj < *self->cppobj;
         break;
     case Py_GE:
-        c = *other->rrtype < *self->rrtype ||
-            *self->rrtype == *other->rrtype;
+        c = *other->cppobj < *self->cppobj ||
+            *self->cppobj == *other->cppobj;
         break;
     default:
         PyErr_SetString(PyExc_IndexError,
@@ -334,131 +265,200 @@ RRType_richcmp(s_RRType* self, s_RRType* other, int op) {
 //
 // Common function for RRType_A/NS/etc.
 //
-static PyObject* RRType_createStatic(RRType stc) {
+PyObject* RRType_createStatic(RRType stc) {
     s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
     if (ret != NULL) {
-        ret->rrtype = new RRType(stc);
+        ret->cppobj = new RRType(stc);
     }
     return (ret);
 }
 
-static PyObject*
+PyObject*
 RRType_NSEC3PARAM(s_RRType*) {
     return (RRType_createStatic(RRType::NSEC3PARAM()));
 }
 
-static PyObject*
+PyObject*
 RRType_DNAME(s_RRType*) {
     return (RRType_createStatic(RRType::DNAME()));
 }
 
-static PyObject*
+PyObject*
 RRType_PTR(s_RRType*) {
     return (RRType_createStatic(RRType::PTR()));
 }
 
-static PyObject*
+PyObject*
 RRType_MX(s_RRType*) {
     return (RRType_createStatic(RRType::MX()));
 }
 
-static PyObject*
+PyObject*
 RRType_DNSKEY(s_RRType*) {
     return (RRType_createStatic(RRType::DNSKEY()));
 }
 
-static PyObject*
+PyObject*
 RRType_TXT(s_RRType*) {
     return (RRType_createStatic(RRType::TXT()));
 }
 
-static PyObject*
+PyObject*
 RRType_RRSIG(s_RRType*) {
     return (RRType_createStatic(RRType::RRSIG()));
 }
 
-static PyObject*
+PyObject*
 RRType_NSEC(s_RRType*) {
     return (RRType_createStatic(RRType::NSEC()));
 }
 
-static PyObject*
+PyObject*
 RRType_AAAA(s_RRType*) {
     return (RRType_createStatic(RRType::AAAA()));
 }
 
-static PyObject*
+PyObject*
 RRType_DS(s_RRType*) {
     return (RRType_createStatic(RRType::DS()));
 }
 
-static PyObject*
+PyObject*
 RRType_OPT(s_RRType*) {
     return (RRType_createStatic(RRType::OPT()));
 }
 
-static PyObject*
+PyObject*
 RRType_A(s_RRType*) {
     return (RRType_createStatic(RRType::A()));
 }
 
-static PyObject*
+PyObject*
 RRType_NS(s_RRType*) {
     return (RRType_createStatic(RRType::NS()));
 }
 
-static PyObject*
+PyObject*
 RRType_CNAME(s_RRType*) {
     return (RRType_createStatic(RRType::CNAME()));
 }
 
-static PyObject*
+PyObject*
 RRType_SOA(s_RRType*) {
     return (RRType_createStatic(RRType::SOA()));
 }
 
-static PyObject*
+PyObject*
 RRType_NSEC3(s_RRType*) {
     return (RRType_createStatic(RRType::NSEC3()));
 }
 
-static PyObject*
+PyObject*
 RRType_IXFR(s_RRType*) {
     return (RRType_createStatic(RRType::IXFR()));
 }
 
-static PyObject*
+PyObject*
 RRType_AXFR(s_RRType*) {
     return (RRType_createStatic(RRType::AXFR()));
 }
 
-static PyObject*
+PyObject*
 RRType_ANY(s_RRType*) {
     return (RRType_createStatic(RRType::ANY()));
 }
 
+} // end anonymous namespace
+
+namespace isc {
+namespace dns {
+namespace python {
 
-// end of RRType
+PyObject* po_InvalidRRType;
+PyObject* po_IncompleteRRType;
+
+// 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.
+PyTypeObject rrtype_type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "pydnspp.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
+    "The RRType class encapsulates DNS resource record types.\n\n"
+    "This class manages the 16-bit integer type codes in quite a straightforward "
+    "way. The only non trivial task is to handle textual representations of "
+    "RR types, such as \"A\", \"AAAA\", or \"TYPE65534\".",
+    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
+    NULL,                               // tp_del
+    0                                   // tp_version_tag
+};
 
+PyObject*
+createRRTypeObject(const RRType& source) {
+    RRTypeContainer container(PyObject_New(s_RRType, &rrtype_type));
+    container.set(new RRType(source));
+    return (container.release());
+}
 
-// Module Initialization, all statics are initialized here
 bool
-initModulePart_RRType(PyObject* mod) {
-    // Add the exceptions to the module
-    po_InvalidRRType = PyErr_NewException("pydnspp.InvalidRRType", NULL, NULL);
-    PyModule_AddObject(mod, "InvalidRRType", po_InvalidRRType);
-    po_IncompleteRRType = PyErr_NewException("pydnspp.IncompleteRRType", NULL, NULL);
-    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);
+PyRRType_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &rrtype_type));
+}
+
+const RRType&
+PyRRType_ToRRType(const PyObject* rrtype_obj) {
+    if (rrtype_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in RRType PyObject conversion");
     }
-    Py_INCREF(&rrtype_type);
-    PyModule_AddObject(mod, "RRType",
-                       reinterpret_cast<PyObject*>(&rrtype_type));
-    
-    return (true);
+    const s_RRType* rrtype = static_cast<const s_RRType*>(rrtype_obj);
+    return (*rrtype->cppobj);
 }
+
+
+} // end namespace python
+} // end namespace dns
+} // end namespace isc
diff --git a/src/lib/dns/python/rrtype_python.h b/src/lib/dns/python/rrtype_python.h
new file mode 100644
index 0000000..596598e
--- /dev/null
+++ b/src/lib/dns/python/rrtype_python.h
@@ -0,0 +1,68 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __PYTHON_RRTYPE_H
+#define __PYTHON_RRTYPE_H 1
+
+#include <Python.h>
+
+namespace isc {
+namespace dns {
+class RRType;
+
+namespace python {
+
+extern PyObject* po_InvalidRRType;
+extern PyObject* po_IncompleteRRType;
+
+extern PyTypeObject rrtype_type;
+
+/// This is a simple shortcut to create a python RRType object (in the
+/// form of a pointer to PyObject) with minimal exception safety.
+/// On success, it returns a valid pointer to PyObject with a reference
+/// counter of 1; if something goes wrong it throws an exception (it never
+/// returns a NULL pointer).
+/// This function is expected to be called within a try block
+/// followed by necessary setup for python exception.
+PyObject* createRRTypeObject(const RRType& source);
+
+/// \brief Checks if the given python object is a RRType object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type RRType, false otherwise
+bool PyRRType_Check(PyObject* obj);
+
+/// \brief Returns a reference to the RRType object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type RRType; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyRRType_Check()
+///
+/// \note This is not a copy; if the RRType is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rrtype_obj The rrtype object to convert
+const RRType& PyRRType_ToRRType(const PyObject* rrtype_obj);
+
+
+} // namespace python
+} // namespace dns
+} // namespace isc
+#endif // __PYTHON_RRTYPE_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/python/tests/Makefile.am b/src/lib/dns/python/tests/Makefile.am
index 61d7df6..d1273f3 100644
--- a/src/lib/dns/python/tests/Makefile.am
+++ b/src/lib/dns/python/tests/Makefile.am
@@ -24,7 +24,7 @@ EXTRA_DIST += testutil.py
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/dns/python/tsig_python.cc b/src/lib/dns/python/tsig_python.cc
index db93a08..0764e33 100644
--- a/src/lib/dns/python/tsig_python.cc
+++ b/src/lib/dns/python/tsig_python.cc
@@ -37,23 +37,18 @@ using namespace isc::util::python;
 using namespace isc::dns;
 using namespace isc::dns::python;
 
-//
-// Definition of the classes
-//
-
 // For each class, we need a struct, a helper functions (init, destroy,
 // and static wrappers around the methods we export), a list of methods,
 // and a type description
 
-//
-// TSIGContext
-//
-
-// Trivial constructor.
-s_TSIGContext::s_TSIGContext() : cppobj(NULL) {
-}
-
 namespace {
+// The s_* Class simply covers one instantiation of the object
+class s_TSIGContext : public PyObject {
+public:
+    s_TSIGContext() : cppobj(NULL) {};
+    TSIGContext* cppobj;
+};
+
 // Shortcut type which would be convenient for adding class variables safely.
 typedef CPPPyObjectContainer<s_TSIGContext, TSIGContext> TSIGContextContainer;
 
@@ -101,23 +96,23 @@ int
 TSIGContext_init(s_TSIGContext* self, PyObject* args) {
     try {
         // "From key" constructor
-        const s_TSIGKey* tsigkey_obj;
+        const PyObject* tsigkey_obj;
         if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey_obj)) {
-            self->cppobj = new TSIGContext(*tsigkey_obj->cppobj);
+            self->cppobj = new TSIGContext(PyTSIGKey_ToTSIGKey(tsigkey_obj));
             return (0);
         }
 
         // "From key param + keyring" constructor
         PyErr_Clear();
-        const s_Name* keyname_obj;
-        const s_Name* algname_obj;
-        const s_TSIGKeyRing* keyring_obj;
+        const PyObject* keyname_obj;
+        const PyObject* algname_obj;
+        const PyObject* keyring_obj;
         if (PyArg_ParseTuple(args, "O!O!O!", &name_type, &keyname_obj,
                              &name_type, &algname_obj, &tsigkeyring_type,
                              &keyring_obj)) {
-            self->cppobj = new TSIGContext(*keyname_obj->cppobj,
-                                           *algname_obj->cppobj,
-                                           *keyring_obj->cppobj);
+            self->cppobj = new TSIGContext(PyName_ToName(keyname_obj),
+                                           PyName_ToName(algname_obj),
+                                           PyTSIGKeyRing_ToTSIGKeyRing(keyring_obj));
             return (0);
         }
     } catch (const exception& ex) {
@@ -153,7 +148,7 @@ PyObject*
 TSIGContext_getError(s_TSIGContext* self) {
     try {
         PyObjectContainer container(createTSIGErrorObject(
-                                        self->cppobj->getError()));
+                                    self->cppobj->getError()));
         return (Py_BuildValue("O", container.get()));
     } catch (const exception& ex) {
         const string ex_what =
@@ -205,13 +200,13 @@ PyObject*
 TSIGContext_verify(s_TSIGContext* self, PyObject* args) {
     const char* data;
     Py_ssize_t data_len;
-    s_TSIGRecord* py_record;
+    PyObject* py_record;
     PyObject* py_maybe_none;
-    TSIGRecord* record;
+    const TSIGRecord* record;
 
     if (PyArg_ParseTuple(args, "O!y#", &tsigrecord_type, &py_record,
                          &data, &data_len)) {
-        record = py_record->cppobj;
+        record = &PyTSIGRecord_ToTSIGRecord(py_record);
     } else if (PyArg_ParseTuple(args, "Oy#", &py_maybe_none, &data,
                                 &data_len)) {
         record = NULL;
@@ -264,7 +259,7 @@ PyTypeObject tsigcontext_type = {
     NULL,                               // tp_as_number
     NULL,                               // tp_as_sequence
     NULL,                               // tp_as_mapping
-    NULL,                               // tp_hash 
+    NULL,                               // tp_hash
     NULL,                               // tp_call
     NULL,                               // tp_str
     NULL,                               // tp_getattro
@@ -307,58 +302,24 @@ PyTypeObject tsigcontext_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
 bool
-initModulePart_TSIGContext(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&tsigcontext_type) < 0) {
-        return (false);
+PyTSIGContext_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
-    void* p = &tsigcontext_type;
-    if (PyModule_AddObject(mod, "TSIGContext",
-                           static_cast<PyObject*>(p)) < 0) {
-        return (false);
-    }
-    Py_INCREF(&tsigcontext_type);
+    return (PyObject_TypeCheck(obj, &tsigcontext_type));
+}
 
-    try {
-        // Class specific exceptions
-        po_TSIGContextError = PyErr_NewException("pydnspp.TSIGContextError",
-                                                 po_IscException, NULL);
-        PyObjectContainer(po_TSIGContextError).installToModule(
-            mod, "TSIGContextError");
-
-        // Constant class variables
-        installClassVariable(tsigcontext_type, "STATE_INIT",
-                             Py_BuildValue("I", TSIGContext::INIT));
-        installClassVariable(tsigcontext_type, "STATE_SENT_REQUEST",
-                             Py_BuildValue("I", TSIGContext::SENT_REQUEST));
-        installClassVariable(tsigcontext_type, "STATE_RECEIVED_REQUEST",
-                             Py_BuildValue("I", TSIGContext::RECEIVED_REQUEST));
-        installClassVariable(tsigcontext_type, "STATE_SENT_RESPONSE",
-                             Py_BuildValue("I", TSIGContext::SENT_RESPONSE));
-        installClassVariable(tsigcontext_type, "STATE_VERIFIED_RESPONSE",
-                             Py_BuildValue("I",
-                                           TSIGContext::VERIFIED_RESPONSE));
-
-        installClassVariable(tsigcontext_type, "DEFAULT_FUDGE",
-                             Py_BuildValue("H", TSIGContext::DEFAULT_FUDGE));
-    } catch (const exception& ex) {
-        const string ex_what =
-            "Unexpected failure in TSIGContext initialization: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-        return (false);
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure in TSIGContext initialization");
-        return (false);
+TSIGContext&
+PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj) {
+    if (tsigcontext_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in TSIGContext PyObject conversion");
     }
-
-    return (true);
+    s_TSIGContext* tsigcontext = static_cast<s_TSIGContext*>(tsigcontext_obj);
+    return (*tsigcontext->cppobj);
 }
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/tsig_python.h b/src/lib/dns/python/tsig_python.h
index f9b4f7b..e4e9fff 100644
--- a/src/lib/dns/python/tsig_python.h
+++ b/src/lib/dns/python/tsig_python.h
@@ -23,19 +23,31 @@ class TSIGContext;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object
-class s_TSIGContext : public PyObject {
-public:
-    s_TSIGContext();
-    TSIGContext* cppobj;
-};
-
 extern PyTypeObject tsigcontext_type;
 
 // Class specific exceptions
 extern PyObject* po_TSIGContextError;
 
-bool initModulePart_TSIGContext(PyObject* mod);
+/// \brief Checks if the given python object is a TSIGContext object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type TSIGContext, false otherwise
+bool PyTSIGContext_Check(PyObject* obj);
+
+/// \brief Returns a reference to the TSIGContext object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type TSIGContext; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyTSIGContext_Check()
+///
+/// \note This is not a copy; if the TSIGContext is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param tsigcontext_obj The tsigcontext object to convert
+TSIGContext& PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj);
+
 
 } // namespace python
 } // namespace dns
diff --git a/src/lib/dns/python/tsig_rdata_python.cc b/src/lib/dns/python/tsig_rdata_python.cc
index 4e4f287..6ec0f09 100644
--- a/src/lib/dns/python/tsig_rdata_python.cc
+++ b/src/lib/dns/python/tsig_rdata_python.cc
@@ -12,6 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
 #include <string>
@@ -32,23 +33,19 @@ using namespace isc::dns;
 using namespace isc::dns::rdata;
 using namespace isc::dns::python;
 
-//
-// Definition of the classes
-//
-
 // For each class, we need a struct, a helper functions (init, destroy,
 // and static wrappers around the methods we export), a list of methods,
 // and a type description
 
-//
-// TSIG RDATA
-//
+namespace {
+// The s_* Class simply covers one instantiation of the object
+class s_TSIG : public PyObject {
+public:
+    s_TSIG() : cppobj(NULL) {};
+    const rdata::any::TSIG* cppobj;
+};
 
-// Trivial constructor.
-s_TSIG::s_TSIG() : cppobj(NULL) {
-}
 
-namespace {
 // Shortcut type which would be convenient for adding class variables safely.
 typedef CPPPyObjectContainer<s_TSIG, any::TSIG> TSIGContainer;
 
@@ -235,7 +232,7 @@ TSIG_toWire(const s_TSIG* const self, PyObject* args) {
                 self, args));
 }
 
-PyObject* 
+PyObject*
 TSIG_richcmp(const s_TSIG* const self,
                    const s_TSIG* const other,
                    const int op)
@@ -302,7 +299,7 @@ PyTypeObject tsig_type = {
     NULL,                               // tp_as_number
     NULL,                               // tp_as_sequence
     NULL,                               // tp_as_mapping
-    NULL,                               // tp_hash 
+    NULL,                               // tp_hash
     NULL,                               // tp_call
     TSIG_str,                       // tp_str
     NULL,                               // tp_getattro
@@ -340,30 +337,31 @@ PyTypeObject tsig_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_TSIG(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&tsig_type) < 0) {
-        return (false);
-    }
-    void* p = &tsig_type;
-    if (PyModule_AddObject(mod, "TSIG", static_cast<PyObject*>(p)) < 0) {
-        return (false);
-    }
-    Py_INCREF(&tsig_type);
-
-    return (true);
-}
-
 PyObject*
 createTSIGObject(const any::TSIG& source) {
-    TSIGContainer container = PyObject_New(s_TSIG, &tsig_type);
+    TSIGContainer container(PyObject_New(s_TSIG, &tsig_type));
     container.set(new any::TSIG(source));
     return (container.release());
 }
+
+bool
+PyTSIG_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
+    }
+    return (PyObject_TypeCheck(obj, &tsig_type));
+}
+
+const any::TSIG&
+PyTSIG_ToTSIG(const PyObject* tsig_obj) {
+    if (tsig_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in TSIG PyObject conversion");
+    }
+    const s_TSIG* tsig = static_cast<const s_TSIG*>(tsig_obj);
+    return (*tsig->cppobj);
+}
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/tsig_rdata_python.h b/src/lib/dns/python/tsig_rdata_python.h
index e5e0c6c..a84d9e8 100644
--- a/src/lib/dns/python/tsig_rdata_python.h
+++ b/src/lib/dns/python/tsig_rdata_python.h
@@ -27,17 +27,8 @@ class TSIG;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object
-class s_TSIG : public PyObject {
-public:
-    s_TSIG();
-    const rdata::any::TSIG* cppobj;
-};
-
 extern PyTypeObject tsig_type;
 
-bool initModulePart_TSIG(PyObject* mod);
-
 /// This is A simple shortcut to create a python TSIG object (in the
 /// form of a pointer to PyObject) with minimal exception safety.
 /// On success, it returns a valid pointer to PyObject with a reference
@@ -47,6 +38,26 @@ bool initModulePart_TSIG(PyObject* mod);
 /// followed by necessary setup for python exception.
 PyObject* createTSIGObject(const rdata::any::TSIG& source);
 
+/// \brief Checks if the given python object is a TSIG object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type TSIG, false otherwise
+bool PyTSIG_Check(PyObject* obj);
+
+/// \brief Returns a reference to the TSIG object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type TSIG; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyTSIG_Check()
+///
+/// \note This is not a copy; if the TSIG is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param tsig_obj The tsig object to convert
+const rdata::any::TSIG& PyTSIG_ToTSIG(const PyObject* tsig_obj);
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/tsigerror_python.cc b/src/lib/dns/python/tsigerror_python.cc
index 0ad4716..7a0217e 100644
--- a/src/lib/dns/python/tsigerror_python.cc
+++ b/src/lib/dns/python/tsigerror_python.cc
@@ -30,26 +30,21 @@ using namespace isc::util::python;
 using namespace isc::dns;
 using namespace isc::dns::python;
 
-//
-// Definition of the classes
-//
-
 // For each class, we need a struct, a helper functions (init, destroy,
 // and static wrappers around the methods we export), a list of methods,
 // and a type description
 
-//
-// TSIGError
-//
-
-// Trivial constructor.
-s_TSIGError::s_TSIGError() : cppobj(NULL) {
-}
-
 // Import pydoc text
 #include "tsigerror_python_inc.cc"
 
 namespace {
+// The s_* Class simply covers one instantiation of the object
+class s_TSIGError : public PyObject {
+public:
+    s_TSIGError() : cppobj(NULL) {};
+    const TSIGError* cppobj;
+};
+
 // Shortcut type which would be convenient for adding class variables safely.
 typedef CPPPyObjectContainer<s_TSIGError, TSIGError> TSIGErrorContainer;
 
@@ -107,9 +102,9 @@ TSIGError_init(s_TSIGError* self, PyObject* args) {
 
         // Constructor from Rcode
         PyErr_Clear();
-        s_Rcode* py_rcode;
+        PyObject* py_rcode;
         if (PyArg_ParseTuple(args, "O!", &rcode_type, &py_rcode)) {
-            self->cppobj = new TSIGError(*py_rcode->cppobj);
+            self->cppobj = new TSIGError(PyRcode_ToRcode(py_rcode));
             return (0);
         }
     } catch (const isc::OutOfRange& ex) {
@@ -172,13 +167,8 @@ TSIGError_str(PyObject* self) {
 
 PyObject*
 TSIGError_toRcode(const s_TSIGError* const self) {
-    typedef CPPPyObjectContainer<s_Rcode, Rcode> RcodePyObjectContainer;
-
     try {
-        RcodePyObjectContainer rcode_container(PyObject_New(s_Rcode,
-                                                            &rcode_type));
-        rcode_container.set(new Rcode(self->cppobj->toRcode()));
-        return (rcode_container.release());
+        return (createRcodeObject(self->cppobj->toRcode()));
     } catch (const exception& ex) {
         const string ex_what =
             "Failed to convert TSIGError to Rcode: " + string(ex.what());
@@ -190,7 +180,7 @@ TSIGError_toRcode(const s_TSIGError* const self) {
     return (NULL);
 }
 
-PyObject* 
+PyObject*
 TSIGError_richcmp(const s_TSIGError* const self,
                    const s_TSIGError* const other,
                    const int op)
@@ -252,7 +242,7 @@ PyTypeObject tsigerror_type = {
     NULL,                               // tp_as_number
     NULL,                               // tp_as_sequence
     NULL,                               // tp_as_mapping
-    NULL,                               // tp_hash 
+    NULL,                               // tp_hash
     NULL,                               // tp_call
     // THIS MAY HAVE TO BE CHANGED TO NULL:
     TSIGError_str,                       // tp_str
@@ -290,78 +280,9 @@ PyTypeObject tsigerror_type = {
     0                                   // tp_version_tag
 };
 
-namespace {
-// Trivial shortcut to create and install TSIGError constants.
-inline void
-installTSIGErrorConstant(const char* name, const TSIGError& val) {
-    TSIGErrorContainer container(PyObject_New(s_TSIGError, &tsigerror_type));
-    container.installAsClassVariable(tsigerror_type, name, new TSIGError(val));
-}
-}
-
-// Module Initialization, all statics are initialized here
-bool
-initModulePart_TSIGError(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&tsigerror_type) < 0) {
-        return (false);
-    }
-    void* p = &tsigerror_type;
-    if (PyModule_AddObject(mod, "TSIGError", static_cast<PyObject*>(p)) < 0) {
-        return (false);
-    }
-    Py_INCREF(&tsigerror_type);
-
-    try {
-        // Constant class variables
-        // Error codes (bare values)
-        installClassVariable(tsigerror_type, "BAD_SIG_CODE",
-                             Py_BuildValue("H", TSIGError::BAD_SIG_CODE));
-        installClassVariable(tsigerror_type, "BAD_KEY_CODE",
-                             Py_BuildValue("H", TSIGError::BAD_KEY_CODE));
-        installClassVariable(tsigerror_type, "BAD_TIME_CODE",
-                             Py_BuildValue("H", TSIGError::BAD_TIME_CODE));
-
-        // Error codes (constant objects)
-        installTSIGErrorConstant("NOERROR", TSIGError::NOERROR());
-        installTSIGErrorConstant("FORMERR", TSIGError::FORMERR());
-        installTSIGErrorConstant("SERVFAIL", TSIGError::SERVFAIL());
-        installTSIGErrorConstant("NXDOMAIN", TSIGError::NXDOMAIN());
-        installTSIGErrorConstant("NOTIMP", TSIGError::NOTIMP());
-        installTSIGErrorConstant("REFUSED", TSIGError::REFUSED());
-        installTSIGErrorConstant("YXDOMAIN", TSIGError::YXDOMAIN());
-        installTSIGErrorConstant("YXRRSET", TSIGError::YXRRSET());
-        installTSIGErrorConstant("NXRRSET", TSIGError::NXRRSET());
-        installTSIGErrorConstant("NOTAUTH", TSIGError::NOTAUTH());
-        installTSIGErrorConstant("NOTZONE", TSIGError::NOTZONE());
-        installTSIGErrorConstant("RESERVED11", TSIGError::RESERVED11());
-        installTSIGErrorConstant("RESERVED12", TSIGError::RESERVED12());
-        installTSIGErrorConstant("RESERVED13", TSIGError::RESERVED13());
-        installTSIGErrorConstant("RESERVED14", TSIGError::RESERVED14());
-        installTSIGErrorConstant("RESERVED15", TSIGError::RESERVED15());
-        installTSIGErrorConstant("BAD_SIG", TSIGError::BAD_SIG());
-        installTSIGErrorConstant("BAD_KEY", TSIGError::BAD_KEY());
-        installTSIGErrorConstant("BAD_TIME", TSIGError::BAD_TIME());
-    } catch (const exception& ex) {
-        const string ex_what =
-            "Unexpected failure in TSIGError initialization: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-        return (false);
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure in TSIGError initialization");
-        return (false);
-    }
-
-    return (true);
-}
-
 PyObject*
 createTSIGErrorObject(const TSIGError& source) {
-    TSIGErrorContainer container = PyObject_New(s_TSIGError, &tsigerror_type);
+    TSIGErrorContainer container(PyObject_New(s_TSIGError, &tsigerror_type));
     container.set(new TSIGError(source));
     return (container.release());
 }
diff --git a/src/lib/dns/python/tsigerror_python.h b/src/lib/dns/python/tsigerror_python.h
index 735a480..0b5b630 100644
--- a/src/lib/dns/python/tsigerror_python.h
+++ b/src/lib/dns/python/tsigerror_python.h
@@ -23,17 +23,8 @@ class TSIGError;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object
-class s_TSIGError : public PyObject {
-public:
-    s_TSIGError();
-    const TSIGError* cppobj;
-};
-
 extern PyTypeObject tsigerror_type;
 
-bool initModulePart_TSIGError(PyObject* mod);
-
 /// This is A simple shortcut to create a python TSIGError object (in the
 /// form of a pointer to PyObject) with minimal exception safety.
 /// On success, it returns a valid pointer to PyObject with a reference
@@ -42,6 +33,7 @@ bool initModulePart_TSIGError(PyObject* mod);
 /// This function is expected to be called with in a try block
 /// followed by necessary setup for python exception.
 PyObject* createTSIGErrorObject(const TSIGError& source);
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/tsigkey_python.cc b/src/lib/dns/python/tsigkey_python.cc
index f0906cb..cf79c1a 100644
--- a/src/lib/dns/python/tsigkey_python.cc
+++ b/src/lib/dns/python/tsigkey_python.cc
@@ -31,10 +31,6 @@ using namespace isc::util::python;
 using namespace isc::dns;
 using namespace isc::dns::python;
 
-//
-// Definition of the classes
-//
-
 // For each class, we need a struct, a helper functions (init, destroy,
 // and static wrappers around the methods we export), a list of methods,
 // and a type description
@@ -43,11 +39,14 @@ using namespace isc::dns::python;
 // TSIGKey
 //
 
+namespace {
 // The s_* Class simply covers one instantiation of the object
+class s_TSIGKey : public PyObject {
+public:
+    s_TSIGKey() : cppobj(NULL) {};
+    TSIGKey* cppobj;
+};
 
-s_TSIGKey::s_TSIGKey() : cppobj(NULL) {}
-
-namespace {
 //
 // We declare the functions here, the definitions are below
 // the type definition of the object, since both can use the other
@@ -96,8 +95,8 @@ TSIGKey_init(s_TSIGKey* self, PyObject* args) {
         }
 
         PyErr_Clear();
-        const s_Name* key_name;
-        const s_Name* algorithm_name;
+        const PyObject* key_name;
+        const PyObject* algorithm_name;
         PyObject* bytes_obj;
         const char* secret;
         Py_ssize_t secret_len;
@@ -107,8 +106,8 @@ TSIGKey_init(s_TSIGKey* self, PyObject* args) {
             if (secret_len == 0) {
                 secret = NULL;
             }
-            self->cppobj = new TSIGKey(*key_name->cppobj,
-                                       *algorithm_name->cppobj,
+            self->cppobj = new TSIGKey(PyName_ToName(key_name),
+                                       PyName_ToName(algorithm_name),
                                        secret, secret_len);
             return (0);
         }
@@ -196,7 +195,7 @@ PyTypeObject tsigkey_type = {
     NULL,                               // tp_as_number
     NULL,                               // tp_as_sequence
     NULL,                               // tp_as_mapping
-    NULL,                               // tp_hash 
+    NULL,                               // tp_hash
     NULL,                               // tp_call
     NULL,                               // tp_str
     NULL,                               // tp_getattro
@@ -233,49 +232,20 @@ PyTypeObject tsigkey_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
 bool
-initModulePart_TSIGKey(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&tsigkey_type) < 0) {
-        return (false);
-    }
-    void* p = &tsigkey_type;
-    if (PyModule_AddObject(mod, "TSIGKey", static_cast<PyObject*>(p)) != 0) {
-        return (false);
-    }
-    Py_INCREF(&tsigkey_type);
-
-    try {
-        // Constant class variables
-        installClassVariable(tsigkey_type, "HMACMD5_NAME",
-                             createNameObject(TSIGKey::HMACMD5_NAME()));
-        installClassVariable(tsigkey_type, "HMACSHA1_NAME",
-                             createNameObject(TSIGKey::HMACSHA1_NAME()));
-        installClassVariable(tsigkey_type, "HMACSHA256_NAME",
-                             createNameObject(TSIGKey::HMACSHA256_NAME()));
-        installClassVariable(tsigkey_type, "HMACSHA224_NAME",
-                             createNameObject(TSIGKey::HMACSHA224_NAME()));
-        installClassVariable(tsigkey_type, "HMACSHA384_NAME",
-                             createNameObject(TSIGKey::HMACSHA384_NAME()));
-        installClassVariable(tsigkey_type, "HMACSHA512_NAME",
-                             createNameObject(TSIGKey::HMACSHA512_NAME()));
-    } catch (const exception& ex) {
-        const string ex_what =
-            "Unexpected failure in TSIGKey initialization: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-        return (false);
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure in TSIGKey initialization");
-        return (false);
+PyTSIGKey_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
+    return (PyObject_TypeCheck(obj, &tsigkey_type));
+}
 
-    return (true);
+const TSIGKey&
+PyTSIGKey_ToTSIGKey(const PyObject* tsigkey_obj) {
+    const s_TSIGKey* tsigkey = static_cast<const s_TSIGKey*>(tsigkey_obj);
+    return (*tsigkey->cppobj);
 }
+
 } // namespace python
 } // namespace dns
 } // namespace isc
@@ -287,13 +257,14 @@ initModulePart_TSIGKey(PyObject* mod) {
 // TSIGKeyRing
 //
 
+namespace {
 // The s_* Class simply covers one instantiation of the object
+class s_TSIGKeyRing : public PyObject {
+public:
+    s_TSIGKeyRing() : cppobj(NULL) {};
+    TSIGKeyRing* cppobj;
+};
 
-// The s_* Class simply covers one instantiation of the object
-
-s_TSIGKeyRing::s_TSIGKeyRing() : cppobj(NULL) {}
-
-namespace {
 //
 // We declare the functions here, the definitions are below
 // the type definition of the object, since both can use the other
@@ -329,7 +300,7 @@ TSIGKeyRing_init(s_TSIGKeyRing* self, PyObject* args) {
                         "Invalid arguments to TSIGKeyRing constructor");
         return (-1);
     }
-    
+
     self->cppobj = new(nothrow) TSIGKeyRing();
     if (self->cppobj == NULL) {
         PyErr_SetString(po_IscException, "Allocating TSIGKeyRing failed");
@@ -354,7 +325,7 @@ TSIGKeyRing_size(const s_TSIGKeyRing* const self) {
 PyObject*
 TSIGKeyRing_add(const s_TSIGKeyRing* const self, PyObject* args) {
     s_TSIGKey* tsigkey;
-    
+
     if (PyArg_ParseTuple(args, "O!", &tsigkey_type, &tsigkey)) {
         try {
             const TSIGKeyRing::Result result =
@@ -374,11 +345,11 @@ TSIGKeyRing_add(const s_TSIGKeyRing* const self, PyObject* args) {
 
 PyObject*
 TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) {
-    s_Name* key_name;
+    PyObject* key_name;
 
     if (PyArg_ParseTuple(args, "O!", &name_type, &key_name)) {
         const TSIGKeyRing::Result result =
-            self->cppobj->remove(*key_name->cppobj);
+            self->cppobj->remove(PyName_ToName(key_name));
         return (Py_BuildValue("I", result));
     }
 
@@ -390,13 +361,14 @@ TSIGKeyRing_remove(const s_TSIGKeyRing* self, PyObject* args) {
 
 PyObject*
 TSIGKeyRing_find(const s_TSIGKeyRing* self, PyObject* args) {
-    s_Name* key_name;
-    s_Name* algorithm_name;
+    PyObject* key_name;
+    PyObject* algorithm_name;
 
     if (PyArg_ParseTuple(args, "O!O!", &name_type, &key_name,
                          &name_type, &algorithm_name)) {
         const TSIGKeyRing::FindResult result =
-            self->cppobj->find(*key_name->cppobj, *algorithm_name->cppobj);
+            self->cppobj->find(PyName_ToName(key_name),
+                               PyName_ToName(algorithm_name));
         if (result.key != NULL) {
             s_TSIGKey* key = PyObject_New(s_TSIGKey, &tsigkey_type);
             if (key == NULL) {
@@ -436,7 +408,7 @@ PyTypeObject tsigkeyring_type = {
     NULL,                               // tp_as_number
     NULL,                               // tp_as_sequence
     NULL,                               // tp_as_mapping
-    NULL,                               // tp_hash 
+    NULL,                               // tp_hash
     NULL,                               // tp_call
     NULL,                               // tp_str
     NULL,                               // tp_getattro
@@ -473,27 +445,24 @@ PyTypeObject tsigkeyring_type = {
 };
 
 bool
-initModulePart_TSIGKeyRing(PyObject* mod) {
-    if (PyType_Ready(&tsigkeyring_type) < 0) {
-        return (false);
+PyTSIGKeyRing_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
-    Py_INCREF(&tsigkeyring_type);
-    void* p = &tsigkeyring_type;
-    if (PyModule_AddObject(mod, "TSIGKeyRing",
-                           static_cast<PyObject*>(p)) != 0) {
-        Py_DECREF(&tsigkeyring_type);
-        return (false);
-    }
-
-    addClassVariable(tsigkeyring_type, "SUCCESS",
-                     Py_BuildValue("I", TSIGKeyRing::SUCCESS));
-    addClassVariable(tsigkeyring_type, "EXIST",
-                     Py_BuildValue("I", TSIGKeyRing::EXIST));
-    addClassVariable(tsigkeyring_type, "NOTFOUND",
-                     Py_BuildValue("I", TSIGKeyRing::NOTFOUND));
+    return (PyObject_TypeCheck(obj, &tsigkeyring_type));
+}
 
-    return (true);
+const TSIGKeyRing&
+PyTSIGKeyRing_ToTSIGKeyRing(const PyObject* tsigkeyring_obj) {
+    if (tsigkeyring_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in TSIGKeyRing PyObject conversion");
+    }
+    const s_TSIGKeyRing* tsigkeyring =
+        static_cast<const s_TSIGKeyRing*>(tsigkeyring_obj);
+    return (*tsigkeyring->cppobj);
 }
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/tsigkey_python.h b/src/lib/dns/python/tsigkey_python.h
index 51b3ae7..6c3d2e3 100644
--- a/src/lib/dns/python/tsigkey_python.h
+++ b/src/lib/dns/python/tsigkey_python.h
@@ -24,24 +24,46 @@ class TSIGKeyRing;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object
-class s_TSIGKey : public PyObject {
-public:
-    s_TSIGKey();
-    TSIGKey* cppobj;
-};
-
-class s_TSIGKeyRing : public PyObject {
-public:
-    s_TSIGKeyRing();
-    TSIGKeyRing* cppobj;
-};
-
 extern PyTypeObject tsigkey_type;
 extern PyTypeObject tsigkeyring_type;
 
-bool initModulePart_TSIGKey(PyObject* mod);
-bool initModulePart_TSIGKeyRing(PyObject* mod);
+/// \brief Checks if the given python object is a TSIGKey object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type TSIGKey, false otherwise
+bool PyTSIGKey_Check(PyObject* obj);
+
+/// \brief Returns a reference to the TSIGKey object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type TSIGKey; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyTSIGKey_Check()
+///
+/// \note This is not a copy; if the TSIGKey is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param tsigkey_obj The tsigkey object to convert
+const TSIGKey& PyTSIGKey_ToTSIGKey(const PyObject* tsigkey_obj);
+
+/// \brief Checks if the given python object is a TSIGKeyRing object
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type TSIGKeyRing, false otherwise
+bool PyTSIGKeyRing_Check(PyObject* obj);
+
+/// \brief Returns a reference to the TSIGKeyRing object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type TSIGKeyRing; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyTSIGKeyRing_Check()
+///
+/// \note This is not a copy; if the TSIGKeyRing is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param tsigkeyring_obj The tsigkeyring object to convert
+const TSIGKeyRing& PyTSIGKeyRing_ToTSIGKeyRing(const PyObject* tsigkeyring_obj);
 
 } // namespace python
 } // namespace dns
diff --git a/src/lib/dns/python/tsigrecord_python.cc b/src/lib/dns/python/tsigrecord_python.cc
index 8a78b5e..c754dd2 100644
--- a/src/lib/dns/python/tsigrecord_python.cc
+++ b/src/lib/dns/python/tsigrecord_python.cc
@@ -32,10 +32,6 @@ using namespace isc::util::python;
 using namespace isc::dns;
 using namespace isc::dns::python;
 
-//
-// Definition of the classes
-//
-
 // For each class, we need a struct, a helper functions (init, destroy,
 // and static wrappers around the methods we export), a list of methods,
 // and a type description
@@ -44,11 +40,14 @@ using namespace isc::dns::python;
 // TSIGRecord
 //
 
-// Trivial constructor.
-s_TSIGRecord::s_TSIGRecord() : cppobj(NULL) {
-}
-
 namespace {
+// The s_* Class simply covers one instantiation of the object
+class s_TSIGRecord : public PyObject {
+public:
+    s_TSIGRecord() : cppobj(NULL) {};
+    TSIGRecord* cppobj;
+};
+
 // Shortcut type which would be convenient for adding class variables safely.
 typedef CPPPyObjectContainer<s_TSIGRecord, TSIGRecord> TSIGRecordContainer;
 
@@ -102,11 +101,12 @@ PyMethodDef TSIGRecord_methods[] = {
 int
 TSIGRecord_init(s_TSIGRecord* self, PyObject* args) {
     try {
-        const s_Name* py_name;
-        const s_TSIG* py_tsig;
+        const PyObject* py_name;
+        const PyObject* py_tsig;
         if (PyArg_ParseTuple(args, "O!O!", &name_type, &py_name,
                              &tsig_type, &py_tsig)) {
-            self->cppobj = new TSIGRecord(*py_name->cppobj, *py_tsig->cppobj);
+            self->cppobj = new TSIGRecord(PyName_ToName(py_name),
+                                          PyTSIG_ToTSIG(py_tsig));
             return (0);
         }
     } catch (const exception& ex) {
@@ -226,7 +226,7 @@ PyTypeObject tsigrecord_type = {
     NULL,                               // tp_as_number
     NULL,                               // tp_as_sequence
     NULL,                               // tp_as_mapping
-    NULL,                               // tp_hash 
+    NULL,                               // tp_hash
     NULL,                               // tp_call
     TSIGRecord_str,                       // tp_str
     NULL,                               // tp_getattro
@@ -262,50 +262,32 @@ PyTypeObject tsigrecord_type = {
     0                                   // tp_version_tag
 };
 
-// Module Initialization, all statics are initialized here
+PyObject*
+createTSIGRecordObject(const TSIGRecord& source) {
+    TSIGRecordContainer container(PyObject_New(s_TSIGRecord, &tsigrecord_type));
+    container.set(new TSIGRecord(source));
+    return (container.release());
+}
+
 bool
-initModulePart_TSIGRecord(PyObject* mod) {
-    // We initialize the static description object with PyType_Ready(),
-    // then add it to the module. This is not just a check! (leaving
-    // this out results in segmentation faults)
-    if (PyType_Ready(&tsigrecord_type) < 0) {
-        return (false);
-    }
-    void* p = &tsigrecord_type;
-    if (PyModule_AddObject(mod, "TSIGRecord", static_cast<PyObject*>(p)) < 0) {
-        return (false);
+PyTSIGRecord_Check(PyObject* obj) {
+    if (obj == NULL) {
+        isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
     }
-    Py_INCREF(&tsigrecord_type);
+    return (PyObject_TypeCheck(obj, &tsigrecord_type));
+}
 
-    // The following template is the typical procedure for installing class
-    // variables.  If the class doesn't have a class variable, remove the
-    // entire try-catch clauses.
-    try {
-        // Constant class variables
-        installClassVariable(tsigrecord_type, "TSIG_TTL",
-                             Py_BuildValue("I", 0));
-    } catch (const exception& ex) {
-        const string ex_what =
-            "Unexpected failure in TSIGRecord initialization: " +
-            string(ex.what());
-        PyErr_SetString(po_IscException, ex_what.c_str());
-        return (false);
-    } catch (...) {
-        PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure in TSIGRecord initialization");
-        return (false);
+const TSIGRecord&
+PyTSIGRecord_ToTSIGRecord(PyObject* tsigrecord_obj) {
+    if (tsigrecord_obj == NULL) {
+        isc_throw(PyCPPWrapperException,
+                  "obj argument NULL in TSIGRecord PyObject conversion");
     }
-
-    return (true);
+    s_TSIGRecord* tsigrecord = static_cast<s_TSIGRecord*>(tsigrecord_obj);
+    return (*tsigrecord->cppobj);
 }
 
-PyObject*
-createTSIGRecordObject(const TSIGRecord& source) {
-    TSIGRecordContainer container = PyObject_New(s_TSIGRecord,
-                                                 &tsigrecord_type);
-    container.set(new TSIGRecord(source));
-    return (container.release());
-}
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/python/tsigrecord_python.h b/src/lib/dns/python/tsigrecord_python.h
index e0a3526..d6252e1 100644
--- a/src/lib/dns/python/tsigrecord_python.h
+++ b/src/lib/dns/python/tsigrecord_python.h
@@ -23,17 +23,9 @@ class TSIGRecord;
 
 namespace python {
 
-// The s_* Class simply covers one instantiation of the object
-class s_TSIGRecord : public PyObject {
-public:
-    s_TSIGRecord();
-    TSIGRecord* cppobj;
-};
 
 extern PyTypeObject tsigrecord_type;
 
-bool initModulePart_TSIGRecord(PyObject* mod);
-
 /// This is A simple shortcut to create a python TSIGRecord object (in the
 /// form of a pointer to PyObject) with minimal exception safety.
 /// On success, it returns a valid pointer to PyObject with a reference
@@ -43,6 +35,26 @@ bool initModulePart_TSIGRecord(PyObject* mod);
 /// followed by necessary setup for python exception.
 PyObject* createTSIGRecordObject(const TSIGRecord& source);
 
+/// \brief Checks if the given python object is a TSIGRecord object
+///
+/// \exception PyCPPWrapperException if obj is NULL
+///
+/// \param obj The object to check the type of
+/// \return true if the object is of type TSIGRecord, false otherwise
+bool PyTSIGRecord_Check(PyObject* obj);
+
+/// \brief Returns a reference to the TSIGRecord object contained within the given
+///        Python object.
+///
+/// \note The given object MUST be of type TSIGRecord; this can be checked with
+///       either the right call to ParseTuple("O!"), or with PyTSIGRecord_Check()
+///
+/// \note This is not a copy; if the TSIGRecord is needed when the PyObject
+/// may be destroyed, the caller must copy it itself.
+///
+/// \param rrtype_obj The rrtype object to convert
+const TSIGRecord& PyTSIGRecord_ToTSIGRecord(PyObject* tsigrecord_obj);
+
 } // namespace python
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/python/isc/acl/tests/Makefile.am b/src/lib/python/isc/acl/tests/Makefile.am
index 87781d7..42867b2 100644
--- a/src/lib/python/isc/acl/tests/Makefile.am
+++ b/src/lib/python/isc/acl/tests/Makefile.am
@@ -7,7 +7,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/acl/.libs:$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/acl/.libs:$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/python/isc/notify/tests/Makefile.am b/src/lib/python/isc/notify/tests/Makefile.am
index 1427d93..00a8d3c 100644
--- a/src/lib/python/isc/notify/tests/Makefile.am
+++ b/src/lib/python/isc/notify/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/util/python/pycppwrapper_util.h b/src/lib/util/python/pycppwrapper_util.h
index 3f396e2..462e715 100644
--- a/src/lib/util/python/pycppwrapper_util.h
+++ b/src/lib/util/python/pycppwrapper_util.h
@@ -293,7 +293,7 @@ protected:
 /// \c PyObject_New() to the caller.
 template <typename PYSTRUCT, typename CPPCLASS>
 struct CPPPyObjectContainer : public PyObjectContainer {
-    CPPPyObjectContainer(PYSTRUCT* obj) : PyObjectContainer(obj) {}
+    explicit CPPPyObjectContainer(PYSTRUCT* obj) : PyObjectContainer(obj) {}
 
     // This method associates a C++ object with the corresponding python
     // object enclosed in this class.
diff --git a/src/lib/util/python/wrapper_template.cc b/src/lib/util/python/wrapper_template.cc
index a703731..426ced5 100644
--- a/src/lib/util/python/wrapper_template.cc
+++ b/src/lib/util/python/wrapper_template.cc
@@ -299,8 +299,8 @@ initModulePart_ at CPPCLASS@(PyObject* mod) {
 
 PyObject*
 create at CPPCLASS@Object(const @CPPCLASS@& source) {
-    @CPPCLASS at Container container =
-        PyObject_New(s_ at CPPCLASS@, &@cppclass at _type);
+    @CPPCLASS at Container container(PyObject_New(s_ at CPPCLASS@,
+                                               &@cppclass at _type));
     container.set(new @CPPCLASS@(source));
     return (container.release());
 }
diff --git a/src/lib/util/python/wrapper_template.h b/src/lib/util/python/wrapper_template.h
index d68a658..be701e1 100644
--- a/src/lib/util/python/wrapper_template.h
+++ b/src/lib/util/python/wrapper_template.h
@@ -37,15 +37,15 @@ bool initModulePart_ at CPPCLASS@(PyObject* mod);
 // Note: this utility function works only when @CPPCLASS@ is a copy
 // constructable.
 // And, it would only be useful when python binding needs to create this
-// object frequently.  Otherwise, it would (or should) probably better to
+// object frequently.  Otherwise, it would (or should) probably be better to
 // remove the declaration and definition of this function.
 //
-/// This is A simple shortcut to create a python @CPPCLASS@ object (in the
+/// This is a simple shortcut to create a python @CPPCLASS@ object (in the
 /// form of a pointer to PyObject) with minimal exception safety.
 /// On success, it returns a valid pointer to PyObject with a reference
 /// counter of 1; if something goes wrong it throws an exception (it never
 /// returns a NULL pointer).
-/// This function is expected to be called with in a try block
+/// This function is expected to be called within a try block
 /// followed by necessary setup for python exception.
 PyObject* create at CPPCLASS@Object(const @CPPCLASS@& source);
 




More information about the bind10-changes mailing list