diff --git a/CXX/Config.hxx b/CXX/Config.hxx
diff --git a/CXX/Exception.hxx b/CXX/Exception.hxx
diff --git a/CXX/Extensions.hxx b/CXX/Extensions.hxx
diff --git a/CXX/IndirectPythonInterface.cxx b/CXX/IndirectPythonInterface.cxx
index 7286cdf..7aee920 100644
--- a/CXX/IndirectPythonInterface.cxx
+++ b/CXX/IndirectPythonInterface.cxx
@@ -34,10 +34,524 @@
 // DAMAGE.
 //
 //-----------------------------------------------------------------------------
-#include "CXX/WrapPython.h"
 
+#include "CXX/IndirectPythonInterface.hxx"
+
+namespace Py
+{
+bool _CFunction_Check( PyObject *op )   { return op->ob_type == _CFunction_Type(); }
+bool _CObject_Check( PyObject *op )     { return op->ob_type == _CObject_Type(); }
+bool _Complex_Check( PyObject *op )     { return op->ob_type == _Complex_Type(); }
+bool _Dict_Check( PyObject *op )        { return op->ob_type == _Dict_Type(); }
+bool _Float_Check( PyObject *op )       { return op->ob_type == _Float_Type(); }
+bool _Function_Check( PyObject *op )    { return op->ob_type == _Function_Type(); }
+bool _Boolean_Check( PyObject *op )     { return op->ob_type == _Bool_Type(); }
+bool _List_Check( PyObject *op )        { return op->ob_type == _List_Type(); }
+bool _Long_Check( PyObject *op )        { return op->ob_type == _Long_Type(); }
+bool _Method_Check( PyObject *op )      { return op->ob_type == _Method_Type(); }
+bool _Module_Check( PyObject *op )      { return op->ob_type == _Module_Type(); }
+bool _Range_Check( PyObject *op )       { return op->ob_type == _Range_Type(); }
+bool _Slice_Check( PyObject *op )       { return op->ob_type == _Slice_Type(); }
+bool _TraceBack_Check( PyObject *op )   { return op->ob_type == _TraceBack_Type(); }
+bool _Tuple_Check( PyObject *op )       { return op->ob_type == _Tuple_Type(); }
+bool _Type_Check( PyObject *op )        { return op->ob_type == _Type_Type(); }
+bool _Unicode_Check( PyObject *op )     { return op->ob_type == _Unicode_Type(); }
 #if PY_MAJOR_VERSION == 2
-#include "Python2/IndirectPythonInterface.cxx"
+bool _String_Check( PyObject *op )      { return op->ob_type == _String_Type(); }
+bool _Int_Check( PyObject *op )         { return op->ob_type == _Int_Type(); }
+#endif
+#if PY_MAJOR_VERSION >= 3
+bool _Bytes_Check( PyObject *op )       { return op->ob_type == _Bytes_Type(); }
+#endif
+
+#if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
+
+#if defined(MS_WINDOWS)
+#include <windows.h>
+
+
+static HMODULE python_dll;
+
+static PyObject *ptr__Exc_ArithmeticError = NULL;
+static PyObject *ptr__Exc_AssertionError = NULL;
+static PyObject *ptr__Exc_AttributeError = NULL;
+static PyObject *ptr__Exc_EnvironmentError = NULL;
+static PyObject *ptr__Exc_EOFError = NULL;
+static PyObject *ptr__Exc_Exception = NULL;
+static PyObject *ptr__Exc_FloatingPointError = NULL;
+static PyObject *ptr__Exc_ImportError = NULL;
+static PyObject *ptr__Exc_IndexError = NULL;
+static PyObject *ptr__Exc_IOError = NULL;
+static PyObject *ptr__Exc_KeyboardInterrupt = NULL;
+static PyObject *ptr__Exc_KeyError = NULL;
+static PyObject *ptr__Exc_LookupError = NULL;
+static PyObject *ptr__Exc_MemoryError = NULL;
+static PyObject *ptr__Exc_NameError = NULL;
+static PyObject *ptr__Exc_NotImplementedError = NULL;
+static PyObject *ptr__Exc_OSError = NULL;
+static PyObject *ptr__Exc_OverflowError = NULL;
+static PyObject *ptr__Exc_RuntimeError = NULL;
+static PyObject *ptr__Exc_StandardError = NULL;
+static PyObject *ptr__Exc_SyntaxError = NULL;
+static PyObject *ptr__Exc_SystemError = NULL;
+static PyObject *ptr__Exc_SystemExit = NULL;
+static PyObject *ptr__Exc_TypeError = NULL;
+static PyObject *ptr__Exc_ValueError = NULL;
+static PyObject *ptr__Exc_ZeroDivisionError = NULL;
+
+#ifdef MS_WINDOWS
+static PyObject *ptr__Exc_WindowsError = NULL;
+#endif
+
+static PyObject *ptr__Exc_IndentationError = NULL;
+static PyObject *ptr__Exc_TabError = NULL;
+static PyObject *ptr__Exc_UnboundLocalError = NULL;
+static PyObject *ptr__Exc_UnicodeError = NULL;
+static PyObject *ptr__PyNone = NULL;
+static PyObject *ptr__PyFalse = NULL;
+static PyObject *ptr__PyTrue = NULL;
+static PyTypeObject *ptr__CFunction_Type = NULL;
+static PyTypeObject *ptr__CObject_Type = NULL;
+static PyTypeObject *ptr__Complex_Type = NULL;
+static PyTypeObject *ptr__Dict_Type = NULL;
+static PyTypeObject *ptr__Float_Type = NULL;
+static PyTypeObject *ptr__Function_Type = NULL;
+static PyTypeObject *ptr__Bool_Type = NULL;
+static PyTypeObject *ptr__List_Type = NULL;
+static PyTypeObject *ptr__Long_Type = NULL;
+static PyTypeObject *ptr__Method_Type = NULL;
+static PyTypeObject *ptr__Module_Type = NULL;
+static PyTypeObject *ptr__Range_Type = NULL;
+static PyTypeObject *ptr__Slice_Type = NULL;
+static PyTypeObject *ptr__TraceBack_Type = NULL;
+static PyTypeObject *ptr__Tuple_Type = NULL;
+static PyTypeObject *ptr__Type_Type = NULL;
+#if PY_MAJOR_VERSION == 2
+static PyTypeObject *ptr__Int_Type = NULL;
+static PyTypeObject *ptr__String_Type = NULL;
+#endif
+#if PY_MAJOR_VERSION >= 3
+static PyTypeObject *ptr__Bytes_Type = NULL;
+#endif
+
+
+static int *ptr_Py_DebugFlag = NULL;
+static int *ptr_Py_InteractiveFlag = NULL;
+static int *ptr_Py_OptimizeFlag = NULL;
+static int *ptr_Py_NoSiteFlag = NULL;
+static int *ptr_Py_VerboseFlag = NULL;
+
+static char **ptr__Py_PackageContext = NULL;
+
+#ifdef Py_REF_DEBUG
+int *ptr_Py_RefTotal;
+#endif
+
+
+//--------------------------------------------------------------------------------
+class GetAddressException
+{
+public:
+    GetAddressException( const char *_name )
+        : name( _name )
+    {}
+    virtual ~GetAddressException() {}
+    const char *name;
+};
+
+
+//--------------------------------------------------------------------------------
+static PyObject *GetPyObjectPointer_As_PyObjectPointer( const char *name )
+{
+    FARPROC addr = GetProcAddress( python_dll, name );
+    if( addr == NULL )
+        throw GetAddressException( name );
+
+    return *(PyObject **)addr;
+}
+
+static PyObject *GetPyObject_As_PyObjectPointer( const char *name )
+{
+    FARPROC addr = GetProcAddress( python_dll, name );
+    if( addr == NULL )
+        throw GetAddressException( name );
+
+    return (PyObject *)addr;
+}
+
+static PyTypeObject *GetPyTypeObjectPointer_As_PyTypeObjectPointer( const char *name )
+{
+    FARPROC addr = GetProcAddress( python_dll, name );
+    if( addr == NULL )
+        throw GetAddressException( name );
+
+    return *(PyTypeObject **)addr;
+}
+
+static PyTypeObject *GetPyTypeObject_As_PyTypeObjectPointer( const char *name )
+{
+    FARPROC addr = GetProcAddress( python_dll, name );
+    if( addr == NULL )
+        throw GetAddressException( name );
+
+    return (PyTypeObject *)addr;
+}
+
+static int *GetInt_as_IntPointer( const char *name )
+{
+    FARPROC addr = GetProcAddress( python_dll, name );
+    if( addr == NULL )
+        throw GetAddressException( name );
+
+    return (int *)addr;
+}
+
+static char **GetCharPointer_as_CharPointerPointer( const char *name )
+{
+    FARPROC addr = GetProcAddress( python_dll, name );
+    if( addr == NULL )
+        throw GetAddressException( name );
+
+    return (char **)addr;
+}
+
+
+#ifdef _DEBUG
+static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL";
 #else
-#include "Python3/IndirectPythonInterface.cxx"
+static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d.DLL";
+#endif
+
+//--------------------------------------------------------------------------------
+bool InitialisePythonIndirectInterface()
+{
+    char python_dll_name[sizeof(python_dll_name_format)];
+
+    _snprintf( python_dll_name, sizeof(python_dll_name_format) / sizeof(char) - 1, python_dll_name_format, PY_MAJOR_VERSION, PY_MINOR_VERSION );
+
+    python_dll = LoadLibraryA( python_dll_name );
+    if( python_dll == NULL )
+        return false;
+
+    try
+    {
+#ifdef Py_REF_DEBUG
+    ptr_Py_RefTotal             = GetInt_as_IntPointer( "_Py_RefTotal" );
+#endif
+    ptr_Py_DebugFlag            = GetInt_as_IntPointer( "Py_DebugFlag" );
+    ptr_Py_InteractiveFlag      = GetInt_as_IntPointer( "Py_InteractiveFlag" );
+    ptr_Py_OptimizeFlag         = GetInt_as_IntPointer( "Py_OptimizeFlag" );
+    ptr_Py_NoSiteFlag           = GetInt_as_IntPointer( "Py_NoSiteFlag" );
+    ptr_Py_VerboseFlag          = GetInt_as_IntPointer( "Py_VerboseFlag" );
+    ptr__Py_PackageContext      = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" );
+
+    ptr__Exc_ArithmeticError    = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ArithmeticError" );
+    ptr__Exc_AssertionError     = GetPyObjectPointer_As_PyObjectPointer( "PyExc_AssertionError" );
+    ptr__Exc_AttributeError     = GetPyObjectPointer_As_PyObjectPointer( "PyExc_AttributeError" );
+    ptr__Exc_EnvironmentError   = GetPyObjectPointer_As_PyObjectPointer( "PyExc_EnvironmentError" );
+    ptr__Exc_EOFError           = GetPyObjectPointer_As_PyObjectPointer( "PyExc_EOFError" );
+    ptr__Exc_Exception          = GetPyObjectPointer_As_PyObjectPointer( "PyExc_Exception" );
+    ptr__Exc_FloatingPointError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_FloatingPointError" );
+    ptr__Exc_ImportError        = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ImportError" );
+    ptr__Exc_IndexError         = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IndexError" );
+    ptr__Exc_IOError            = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IOError" );
+    ptr__Exc_KeyboardInterrupt  = GetPyObjectPointer_As_PyObjectPointer( "PyExc_KeyboardInterrupt" );
+    ptr__Exc_KeyError           = GetPyObjectPointer_As_PyObjectPointer( "PyExc_KeyError" );
+    ptr__Exc_LookupError        = GetPyObjectPointer_As_PyObjectPointer( "PyExc_LookupError" );
+    ptr__Exc_MemoryError        = GetPyObjectPointer_As_PyObjectPointer( "PyExc_MemoryError" );
+    ptr__Exc_NameError          = GetPyObjectPointer_As_PyObjectPointer( "PyExc_NameError" );
+    ptr__Exc_NotImplementedError= GetPyObjectPointer_As_PyObjectPointer( "PyExc_NotImplementedError" );
+    ptr__Exc_OSError            = GetPyObjectPointer_As_PyObjectPointer( "PyExc_OSError" );
+    ptr__Exc_OverflowError      = GetPyObjectPointer_As_PyObjectPointer( "PyExc_OverflowError" );
+    ptr__Exc_RuntimeError       = GetPyObjectPointer_As_PyObjectPointer( "PyExc_RuntimeError" );
+    ptr__Exc_StandardError      = GetPyObjectPointer_As_PyObjectPointer( "PyExc_StandardError" );
+    ptr__Exc_SyntaxError        = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SyntaxError" );
+    ptr__Exc_SystemError        = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SystemError" );
+    ptr__Exc_SystemExit         = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SystemExit" );
+    ptr__Exc_TypeError          = GetPyObjectPointer_As_PyObjectPointer( "PyExc_TypeError" );
+    ptr__Exc_ValueError         = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ValueError" );
+#ifdef MS_WINDOWS
+    ptr__Exc_WindowsError       = GetPyObjectPointer_As_PyObjectPointer( "PyExc_WindowsError" );
+#endif
+    ptr__Exc_ZeroDivisionError  = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ZeroDivisionError" );
+    ptr__Exc_IndentationError   = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IndentationError" );
+    ptr__Exc_TabError           = GetPyObjectPointer_As_PyObjectPointer( "PyExc_TabError" );
+    ptr__Exc_UnboundLocalError  = GetPyObjectPointer_As_PyObjectPointer( "PyExc_UnboundLocalError" );
+    ptr__Exc_UnicodeError       = GetPyObjectPointer_As_PyObjectPointer( "PyExc_UnicodeError" );
+    ptr__PyNone                 = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" );
+
+    ptr__PyFalse                = GetPyObject_As_PyObjectPointer( "_Py_ZeroStruct" );
+    ptr__PyTrue                 = GetPyObject_As_PyObjectPointer( "_Py_TrueStruct" );
+
+    ptr__CFunction_Type         = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" );
+    ptr__CObject_Type           = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" );
+    ptr__Complex_Type           = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" );
+    ptr__Dict_Type              = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" );
+    ptr__Float_Type             = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" );
+    ptr__Function_Type          = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" );
+    ptr__Bool_Type              = GetPyTypeObject_As_PyTypeObjectPointer( "PyBool_Type" );
+    ptr__List_Type              = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" );
+    ptr__Long_Type              = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" );
+    ptr__Method_Type            = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" );
+    ptr__Module_Type            = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" );
+    ptr__Range_Type             = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" );
+    ptr__Slice_Type             = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" );
+    ptr__TraceBack_Type         = GetPyTypeObject_As_PyTypeObjectPointer( "PyTraceBack_Type" );
+    ptr__Tuple_Type             = GetPyTypeObject_As_PyTypeObjectPointer( "PyTuple_Type" );
+    ptr__Type_Type              = GetPyTypeObject_As_PyTypeObjectPointer( "PyType_Type" );
+    ptr__Unicode_Type           = GetPyTypeObject_As_PyTypeObjectPointer( "PyUnicode_Type" );
+#if PY_MAJOR_VERSION == 2
+    ptr__String_Type            = GetPyTypeObject_As_PyTypeObjectPointer( "PyString_Type" );
+    ptr__Int_Type               = GetPyTypeObject_As_PyTypeObjectPointer( "PyInt_Type" );
+#endif
+#if PY_MAJOR_VERSION >= 3
+    ptr__Bytes_Type             = GetPyTypeObject_As_PyTypeObjectPointer( "PyBytes_Type" );
+#endif
+    }
+    catch( GetAddressException &e )
+    {
+        OutputDebugStringA( python_dll_name );
+        OutputDebugStringA( " does not contain symbol " );
+        OutputDebugStringA( e.name );
+        OutputDebugStringA( "\n" );
+
+        return false;
+    }
+
+    return true;
+}
+
+//
+//    Wrap variables as function calls
+//
+PyObject *_Exc_ArithmeticError()        { return ptr__Exc_ArithmeticError; }
+PyObject *_Exc_AssertionError()         { return ptr__Exc_AssertionError; }
+PyObject *_Exc_AttributeError()         { return ptr__Exc_AttributeError; }
+PyObject *_Exc_EnvironmentError()       { return ptr__Exc_EnvironmentError; }
+PyObject *_Exc_EOFError()               { return ptr__Exc_EOFError; }
+PyObject *_Exc_Exception()              { return ptr__Exc_Exception; }
+PyObject *_Exc_FloatingPointError()     { return ptr__Exc_FloatingPointError; }
+PyObject *_Exc_ImportError()            { return ptr__Exc_ImportError; }
+PyObject *_Exc_IndexError()             { return ptr__Exc_IndexError; }
+PyObject *_Exc_IOError()                { return ptr__Exc_IOError; }
+PyObject *_Exc_KeyboardInterrupt()      { return ptr__Exc_KeyboardInterrupt; }
+PyObject *_Exc_KeyError()               { return ptr__Exc_KeyError; }
+PyObject *_Exc_LookupError()            { return ptr__Exc_LookupError; }
+PyObject *_Exc_MemoryError()            { return ptr__Exc_MemoryError; }
+PyObject *_Exc_NameError()              { return ptr__Exc_NameError; }
+PyObject *_Exc_NotImplementedError()    { return ptr__Exc_NotImplementedError; }
+PyObject *_Exc_OSError()                { return ptr__Exc_OSError; }
+PyObject *_Exc_OverflowError()          { return ptr__Exc_OverflowError; }
+PyObject *_Exc_RuntimeError()           { return ptr__Exc_RuntimeError; }
+PyObject *_Exc_StandardError()          { return ptr__Exc_StandardError; }
+PyObject *_Exc_SyntaxError()            { return ptr__Exc_SyntaxError; }
+PyObject *_Exc_SystemError()            { return ptr__Exc_SystemError; }
+PyObject *_Exc_SystemExit()             { return ptr__Exc_SystemExit; }
+PyObject *_Exc_TypeError()              { return ptr__Exc_TypeError; }
+PyObject *_Exc_ValueError()             { return ptr__Exc_ValueError; }
+#ifdef MS_WINDOWS
+PyObject *_Exc_WindowsError()           { return ptr__Exc_WindowsError; }
+#endif
+PyObject *_Exc_ZeroDivisionError()      { return ptr__Exc_ZeroDivisionError; }
+PyObject *_Exc_IndentationError()       { return ptr__Exc_IndentationError; }
+PyObject *_Exc_TabError()               { return ptr__Exc_TabError; }
+PyObject *_Exc_UnboundLocalError()      { return ptr__Exc_UnboundLocalError; }
+PyObject *_Exc_UnicodeError()           { return ptr__Exc_UnicodeError; }
+
+//
+//    wrap items in Object.h
+//
+PyObject *_None()                       { return ptr__PyNone; }
+
+PyObject *_False()                      { return ptr__PyFalse; }
+PyObject *_True()                       { return ptr__PyTrue; }
+
+PyTypeObject *_CFunction_Type()         { return ptr__CFunction_Type; }
+PyTypeObject *_CObject_Type()           { return ptr__CObject_Type; }
+PyTypeObject *_Complex_Type()           { return ptr__Complex_Type; }
+PyTypeObject *_Dict_Type()              { return ptr__Dict_Type; }
+PyTypeObject *_Float_Type()             { return ptr__Float_Type; }
+PyTypeObject *_Function_Type()          { return ptr__Function_Type; }
+PyTypeObject *_Bool_Type()              { return ptr__Bool_Type; }
+PyTypeObject *_List_Type()              { return ptr__List_Type; }
+PyTypeObject *_Long_Type()              { return ptr__Long_Type; }
+PyTypeObject *_Method_Type()            { return ptr__Method_Type; }
+PyTypeObject *_Module_Type()            { return ptr__Module_Type; }
+PyTypeObject *_Range_Type()             { return ptr__Range_Type; }
+PyTypeObject *_Slice_Type()             { return ptr__Slice_Type; }
+PyTypeObject *_TraceBack_Type()         { return ptr__TraceBack_Type; }
+PyTypeObject *_Tuple_Type()             { return ptr__Tuple_Type; }
+PyTypeObject *_Type_Type()              { return ptr__Type_Type; }
+PyTypeObject *_Unicode_Type()           { return ptr__Unicode_Type; }
+#if PY_MAJOR_VERSION == 2
+PyTypeObject *_String_Type()            { return ptr__String_Type; }
+PyTypeObject *_Int_Type()               { return ptr__Int_Type; }
+#endif
+#if PY_MAJOR_VERSION >= 3
+PyTypeObject *_Bytes_Type()             { return ptr__Bytes_Type; }
+#endif
+
+char *__Py_PackageContext()             { return *ptr__Py_PackageContext; }
+
+
+//
+//    wrap the Python Flag variables
+//
+int &_Py_DebugFlag()                    { return *ptr_Py_DebugFlag; }
+int &_Py_InteractiveFlag()              { return *ptr_Py_InteractiveFlag; }
+int &_Py_OptimizeFlag()                 { return *ptr_Py_OptimizeFlag; }
+int &_Py_NoSiteFlag()                   { return *ptr_Py_NoSiteFlag; }
+int &_Py_VerboseFlag()                  { return *ptr_Py_VerboseFlag; }
+
+#if 0
+#define Py_INCREF(op) (                         \
+    _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
+    ((PyObject*)(op))->ob_refcnt++)
+
+#define Py_DECREF(op)                           \
+    if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA   \
+        --((PyObject*)(op))->ob_refcnt != 0)    \
+        _Py_CHECK_REFCNT(op)                    \
+    else                                        \
+        _Py_Dealloc((PyObject *)(op))
+#endif
+
+void _XINCREF( PyObject *op )
+{
+    // This function must match the contents of Py_XINCREF(op)
+    if( op == NULL )
+        return;
+
+#ifdef Py_REF_DEBUG
+    (*ptr_Py_RefTotal)++;
+#endif
+    (op)->ob_refcnt++;
+
+}
+
+void _XDECREF( PyObject *op )
+{
+    // This function must match the contents of Py_XDECREF(op);
+    if( op == NULL )
+        return;
+
+#ifdef Py_REF_DEBUG
+    (*ptr_Py_RefTotal)--;
+#endif
+
+    if (--(op)->ob_refcnt == 0)
+        _Py_Dealloc((PyObject *)(op));
+}
+
+
+#else
+#error "Can only delay load under Win32"
+#endif
+
+#else
+
+//================================================================================
+//
+//    Map onto Macros
+//
+//================================================================================
+
+//
+//    Wrap variables as function calls
+//
+
+PyObject *_Exc_ArithmeticError()        { return ::PyExc_ArithmeticError; }
+PyObject *_Exc_AssertionError()         { return ::PyExc_AssertionError; }
+PyObject *_Exc_AttributeError()         { return ::PyExc_AttributeError; }
+PyObject *_Exc_EnvironmentError()       { return ::PyExc_EnvironmentError; }
+PyObject *_Exc_EOFError()               { return ::PyExc_EOFError; }
+PyObject *_Exc_Exception()              { return ::PyExc_Exception; }
+PyObject *_Exc_FloatingPointError()     { return ::PyExc_FloatingPointError; }
+PyObject *_Exc_ImportError()            { return ::PyExc_ImportError; }
+PyObject *_Exc_IndexError()             { return ::PyExc_IndexError; }
+PyObject *_Exc_IOError()                { return ::PyExc_IOError; }
+PyObject *_Exc_KeyboardInterrupt()      { return ::PyExc_KeyboardInterrupt; }
+PyObject *_Exc_KeyError()               { return ::PyExc_KeyError; }
+PyObject *_Exc_LookupError()            { return ::PyExc_LookupError; }
+PyObject *_Exc_MemoryError()            { return ::PyExc_MemoryError; }
+PyObject *_Exc_NameError()              { return ::PyExc_NameError; }
+PyObject *_Exc_NotImplementedError()    { return ::PyExc_NotImplementedError; }
+PyObject *_Exc_OSError()                { return ::PyExc_OSError; }
+PyObject *_Exc_OverflowError()          { return ::PyExc_OverflowError; }
+PyObject *_Exc_RuntimeError()           { return ::PyExc_RuntimeError; }
+PyObject *_Exc_SyntaxError()            { return ::PyExc_SyntaxError; }
+PyObject *_Exc_SystemError()            { return ::PyExc_SystemError; }
+PyObject *_Exc_SystemExit()             { return ::PyExc_SystemExit; }
+PyObject *_Exc_TypeError()              { return ::PyExc_TypeError; }
+PyObject *_Exc_ValueError()             { return ::PyExc_ValueError; }
+PyObject *_Exc_ZeroDivisionError()      { return ::PyExc_ZeroDivisionError; }
+PyObject *_Exc_IndentationError()       { return ::PyExc_IndentationError; }
+PyObject *_Exc_TabError()               { return ::PyExc_TabError; }
+PyObject *_Exc_UnboundLocalError()      { return ::PyExc_UnboundLocalError; }
+PyObject *_Exc_UnicodeError()           { return ::PyExc_UnicodeError; }
+
+#ifdef MS_WINDOWS
+PyObject *_Exc_WindowsError()           { return ::PyExc_WindowsError; }
+#endif
+
+
+
+
+//
+//    wrap items in Object.h
+//
+PyObject *_None()                       { return &::_Py_NoneStruct; }
+
+PyObject *_False()                      { return Py_False; }
+PyObject *_True()                       { return Py_True; }
+
+PyTypeObject *_CFunction_Type()         { return &PyCFunction_Type; }
+PyTypeObject *_CObject_Type()           { return &PyCObject_Type; }
+PyTypeObject *_Complex_Type()           { return &PyComplex_Type; }
+PyTypeObject *_Dict_Type()              { return &PyDict_Type; }
+PyTypeObject *_Float_Type()             { return &PyFloat_Type; }
+PyTypeObject *_Function_Type()          { return &PyFunction_Type; }
+PyTypeObject *_Bool_Type()              { return &PyBool_Type; }
+PyTypeObject *_List_Type()              { return &PyList_Type; }
+PyTypeObject *_Long_Type()              { return &PyLong_Type; }
+PyTypeObject *_Method_Type()            { return &PyMethod_Type; }
+PyTypeObject *_Module_Type()            { return &PyModule_Type; }
+PyTypeObject *_Range_Type()             { return &PyRange_Type; }
+PyTypeObject *_Slice_Type()             { return &PySlice_Type; }
+PyTypeObject *_TraceBack_Type()         { return &PyTraceBack_Type; }
+PyTypeObject *_Tuple_Type()             { return &PyTuple_Type; }
+PyTypeObject *_Type_Type()              { return &PyType_Type; }
+PyTypeObject *_Unicode_Type()           { return &PyUnicode_Type; }
+#if PY_MAJOR_VERSION == 2
+PyTypeObject *_String_Type()            { return &PyString_Type; }
+PyTypeObject *_Int_Type()               { return &PyInt_Type; }
+#endif
+#if PY_MAJOR_VERSION >= 3
+PyTypeObject *_Bytes_Type()             { return &PyBytes_Type; }
+#endif
+
+//
+//    wrap flags
+//
+int &_Py_DebugFlag()                    { return Py_DebugFlag; }
+int &_Py_InteractiveFlag()              { return Py_InteractiveFlag; }
+int &_Py_OptimizeFlag()                 { return Py_OptimizeFlag; }
+int &_Py_NoSiteFlag()                   { return Py_NoSiteFlag; }
+int &_Py_VerboseFlag()                  { return Py_VerboseFlag; }
+char *__Py_PackageContext()             { return _Py_PackageContext; }
+
+//
+//    Needed to keep the abstactions for delayload interface
+//
+void _XINCREF( PyObject *op )
+{
+    Py_XINCREF( op );
+}
+
+void _XDECREF( PyObject *op )
+{
+    Py_XDECREF( op );
+}
+
 #endif
+}
diff --git a/CXX/IndirectPythonInterface.hxx b/CXX/IndirectPythonInterface.hxx
diff --git a/CXX/Objects.hxx b/CXX/Objects.hxx
diff --git a/CXX/Python2/Config.hxx b/CXX/Python2/Config.hxx
diff --git a/CXX/Python2/CxxDebug.hxx b/CXX/Python2/CxxDebug.hxx
diff --git a/CXX/Python2/Exception.hxx b/CXX/Python2/Exception.hxx
index 1ef087c..3acc0ae 100644
--- a/CXX/Python2/Exception.hxx
+++ b/CXX/Python2/Exception.hxx
@@ -163,6 +163,16 @@ namespace Py
         }
     };
     
+    class NotImplementedError: public StandardError
+    {
+    public:
+        NotImplementedError (const std::string& reason)
+            : StandardError()
+        {
+            PyErr_SetString (Py::_Exc_NotImplementedError(), reason.c_str());
+        }
+    };
+    
     class SystemError: public StandardError
     {
     public:
diff --git a/CXX/Python2/ExtensionModule.hxx b/CXX/Python2/ExtensionModule.hxx
diff --git a/CXX/Python2/ExtensionOldType.hxx b/CXX/Python2/ExtensionOldType.hxx
index 8aa2a3e..5e1355b 100644
--- a/CXX/Python2/ExtensionOldType.hxx
+++ b/CXX/Python2/ExtensionOldType.hxx
@@ -74,6 +74,11 @@ namespace Py
             return this;
         }
 
+        Object self()
+        {
+            return asObject( this );
+        }
+
     protected:
         explicit PythonExtension()
         : PythonExtensionBase()
@@ -173,7 +178,7 @@ namespace Py
             Tuple self( 2 );
 
             self[0] = Object( this );
-            self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true );
+            self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );
 
             PyObject *func = PyCFunction_New( &method_def->ext_meth_def, self.ptr() );
 
diff --git a/CXX/Python2/ExtensionType.hxx b/CXX/Python2/ExtensionType.hxx
index 2b41dbb..4128960 100644
--- a/CXX/Python2/ExtensionType.hxx
+++ b/CXX/Python2/ExtensionType.hxx
@@ -45,44 +45,67 @@
 #define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \
     static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \
     { \
-        Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
-        CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
-        Py::Object r( (self->NAME)() ); \
-        return Py::new_reference_to( r.ptr() ); \
+        try \
+        { \
+            Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
+            CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
+            Py::Object r( (self->NAME)() ); \
+            return Py::new_reference_to( r.ptr() ); \
+        } \
+        catch( Py::Exception & ) \
+        { \
+            return 0; \
+        } \
     }
 #define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \
     static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \
     { \
-        Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
-        CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
-        Py::Tuple a( _a ); \
-        Py::Object r( (self->NAME)( a ) ); \
-        return Py::new_reference_to( r.ptr() ); \
+        try \
+        { \
+            Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
+            CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
+            Py::Tuple a( _a ); \
+            Py::Object r( (self->NAME)( a ) ); \
+            return Py::new_reference_to( r.ptr() ); \
+        } \
+        catch( Py::Exception & ) \
+        { \
+            return 0; \
+        } \
     }
 #define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \
     static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \
     { \
-        Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
-        CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
-        Py::Tuple a( _a ); \
-        Py::Dict k; \
-        if( _k != NULL ) \
-            k = _k; \
-        Py::Object r( (self->NAME)( a, k ) ); \
-        return Py::new_reference_to( r.ptr() ); \
+        try \
+        { \
+            Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
+            CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
+            Py::Tuple a( _a ); \
+            Py::Dict k; \
+            if( _k != NULL ) \
+                k = _k; \
+            Py::Object r( (self->NAME)( a, k ) ); \
+            return Py::new_reference_to( r.ptr() ); \
+        } \
+        catch( Py::Exception & ) \
+        { \
+            return 0; \
+        } \
     }
 
 // need to support METH_STATIC and METH_CLASS
 
-#define PYCXX_ADD_NOARGS_METHOD( NAME, docs ) \
-    add_method( #NAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
-#define PYCXX_ADD_VARARGS_METHOD( NAME, docs ) \
-    add_method( #NAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
-#define PYCXX_ADD_KEYWORDS_METHOD( NAME, docs ) \
-    add_method( #NAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
+#define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \
+    add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
+#define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \
+    add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
+#define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \
+    add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
 
 namespace Py
 {
+    extern PythonExtensionBase *getPythonExtensionBase( PyObject *self );
+
     struct PythonClassInstance
     {
         PyObject_HEAD
@@ -131,7 +154,7 @@ namespace Py
                 {
                     new_mt[ i ] = old_mt[ i ];
                 }
-                delete old_mt;
+                delete[] old_mt;
                 m_methods_table = new_mt;
             }
 
@@ -167,10 +190,8 @@ namespace Py
     protected:
         explicit PythonClass( PythonClassInstance *self, Tuple &args, Dict &kwds )
         : PythonExtensionBase()
-        , m_self( self )
+        , m_class_instance( self )
         {
-            // we are a class
-            behaviors().supportClass();
         }
 
         virtual ~PythonClass()
@@ -203,6 +224,12 @@ namespace Py
                 p->set_tp_new( extension_object_new );
                 p->set_tp_init( extension_object_init );
                 p->set_tp_dealloc( extension_object_deallocator );
+                // we are a class
+                p->supportClass();
+
+                // always support get and set attr
+                p->supportGetattro();
+                p->supportSetattro();
             }
 
             return *p;
@@ -238,7 +265,7 @@ namespace Py
                 PythonClassInstance *self = reinterpret_cast<PythonClassInstance *>( _self );
 #ifdef PYCXX_DEBUG
                 std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
-                std::cout << "    self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->cxx_object ) << std::dec << std::endl;
+                std::cout << "    self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
 #endif
 
                 if( self->m_pycxx_object == NULL )
@@ -268,9 +295,10 @@ namespace Py
             PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self );
 #ifdef PYCXX_DEBUG
             std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
-            std::cout << "    self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->cxx_object ) << std::dec << std::endl;
+            std::cout << "    self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
 #endif
             delete self->m_pycxx_object;
+            _self->ob_type->tp_free( _self );
         }
 
     public:
@@ -295,14 +323,19 @@ namespace Py
             return check( ob.ptr() );
         }
 
-        PyObject *selfPtr()
+        virtual PyObject *selfPtr()
+        {
+            return reinterpret_cast<PyObject *>( m_class_instance );
+        }
+
+        virtual Object self()
         {
-            return reinterpret_cast<PyObject *>( m_self );
+            return Object( reinterpret_cast<PyObject *>( m_class_instance ) );
         }
 
     protected:
     private:
-        PythonClassInstance *m_self;
+        PythonClassInstance *m_class_instance;
 
     private:
         //
@@ -361,7 +394,7 @@ namespace Py
         //
         T *getCxxObject( void )
         {
-            return static_cast<T *>( ptr() );
+            return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) );
         }
     };
 } // Namespace Py
diff --git a/CXX/Python2/ExtensionTypeBase.hxx b/CXX/Python2/ExtensionTypeBase.hxx
index eaebe65..ad11029 100644
--- a/CXX/Python2/ExtensionTypeBase.hxx
+++ b/CXX/Python2/ExtensionTypeBase.hxx
@@ -132,7 +132,39 @@ namespace Py
         virtual Py_ssize_t buffer_getsegcount( Py_ssize_t* );
 
     public:
+        // helper functions to call function fn_name with 0 to 9 args
+        Object callOnSelf( const std::string &fn_name );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6,
+                                const Object &arg7 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6,
+                                const Object &arg7, const Object &arg8 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6,
+                                const Object &arg7, const Object &arg8, const Object &arg9 );
+
+    public:
         virtual PyObject *selfPtr() = 0;
+        virtual Object self() = 0;
 
     private:
         void missing_method( void );
diff --git a/CXX/Python2/Extensions.hxx b/CXX/Python2/Extensions.hxx
diff --git a/CXX/Python2/IndirectPythonInterface.hxx b/CXX/Python2/IndirectPythonInterface.hxx
diff --git a/CXX/Python2/Objects.hxx b/CXX/Python2/Objects.hxx
index ce1fa98..286293e 100644
--- a/CXX/Python2/Objects.hxx
+++ b/CXX/Python2/Objects.hxx
@@ -61,6 +61,8 @@ namespace Py
     class String;
     class List;
     template<TEMPLATE_TYPENAME T> class MapBase;
+    class Tuple;
+    class Dict;
 
     // new_reference_to also overloaded below on Object
     inline PyObject* new_reference_to(PyObject* p)
@@ -268,6 +270,10 @@ namespace Py
             return Object (PyObject_GetAttrString (p, const_cast<char*>(s.c_str())), true);
         }
 
+        Object callMemberFunction( const std::string &function_name ) const;
+        Object callMemberFunction( const std::string &function_name, const Tuple &args ) const;
+        Object callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const;
+
         Object getItem (const Object& key) const
         {
             return Object (PyObject_GetItem(p, *key), true);
@@ -1718,7 +1724,6 @@ namespace Py
     template <TEMPLATE_TYPENAME T> bool operator<=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
     template <TEMPLATE_TYPENAME T> bool operator>=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); 
 
-
     extern bool operator==(const Sequence::iterator& left, const Sequence::iterator& right);
     extern bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right);
     extern bool operator< (const Sequence::iterator& left, const Sequence::iterator& right);
@@ -1848,62 +1853,61 @@ namespace Py
         }
 
         String()
-            : SeqBase<Char>( PyString_FromStringAndSize( "", 0 ), true )
+        : SeqBase<Char>( PyString_FromStringAndSize( "", 0 ), true )
         {
             validate();
         }
 
         String( const std::string& v )
-            : SeqBase<Char>( PyString_FromStringAndSize( const_cast<char*>(v.data()),
+        : SeqBase<Char>( PyString_FromStringAndSize( const_cast<char*>(v.data()),
                 static_cast<int>( v.length() ) ), true )
         {
             validate();
         }
 
-        String( const char *s, const char *encoding, const char *error="strict" )
-            : SeqBase<Char>( PyUnicode_Decode( s, strlen( s ), encoding, error ), true )
+        String( const Py_UNICODE *s, int length )
+        : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true )
         {
             validate();
         }
 
-        String( const char *s, int len, const char *encoding, const char *error="strict" )
-            : SeqBase<Char>( PyUnicode_Decode( s, len, encoding, error ), true )
+        String( const char *s, const char *encoding, const char *error="strict" )
+        : SeqBase<Char>( PyUnicode_Decode( s, strlen( s ), encoding, error ), true )
         {
             validate();
         }
 
-        String( const std::string &s, const char *encoding, const char *error="strict" )
-            : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true )
+        String( const char *s, int len, const char *encoding, const char *error="strict" )
+        : SeqBase<Char>( PyUnicode_Decode( s, len, encoding, error ), true )
         {
             validate();
         }
 
-        String( const std::string& v, std::string::size_type vsize )
-            : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v.data()),
-                    static_cast<int>( vsize ) ), true)
+        String( const std::string &s, const char *encoding, const char *error="strict" )
+        : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true )
         {
             validate();
         }
 
         String( const char *v, int vsize )
-            : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true )
+        : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true )
         {
             validate();
         }
 
-        String( const char* v )
-            : SeqBase<Char>( PyString_FromString( v ), true )
+        String( const char *v )
+        : SeqBase<Char>( PyString_FromString( v ), true )
         {
             validate();
         }
 
         // Assignment acquires new ownership of pointer
-        String& operator= ( const Object& rhs )
+        String &operator=( const Object &rhs )
         {
             return *this = *rhs;
         }
 
-        String& operator= (PyObject* rhsp)
+        String& operator= (PyObject *rhsp)
         {
             if( ptr() == rhsp )
                 return *this;
@@ -1917,25 +1921,24 @@ namespace Py
         }
 
         // Assignment from C string
-        String& operator= (const std::string& v)
+        String& operator=( const std::string &v )
         {
             set( PyString_FromStringAndSize( const_cast<char*>( v.data() ),
                     static_cast<int>( v.length() ) ), true );
             return *this;
         }
-        String& operator= (const unicodestring& v)
+        String& operator=( const unicodestring &v )
         {
             set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ),
                     static_cast<int>( v.length() ) ), true );
             return *this;
         }
 
-
         // Encode
         Bytes encode( const char *encoding, const char *error="strict" ) const;
 
         // Queries
-        virtual size_type size () const
+        virtual size_type size() const
         {
             if( isUnicode() )
             {
@@ -1947,7 +1950,7 @@ namespace Py
             }
         }
 
-        operator std::string () const
+        operator std::string() const
         {
             return as_std_string( "utf-8" );
         }
@@ -1966,6 +1969,18 @@ namespace Py
                 throw TypeError("can only return unicodestring from Unicode object");
             }
         }
+
+        const Py_UNICODE *unicode_data() const
+        {
+            if( isUnicode() )
+            {
+                return PyUnicode_AS_UNICODE( ptr() );
+            }
+            else
+            {
+                throw TypeError("can only return unicode_data from Unicode object");
+            }
+        }
     };
     class Bytes: public SeqBase<Char>
     {
@@ -1997,12 +2012,6 @@ namespace Py
             validate();
         }
 
-        Bytes( const std::string& v, std::string::size_type vsize )
-        : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v.data()), static_cast<int>( vsize ) ), true)
-        {
-            validate();
-        }
-
         Bytes( const char *v, int vsize )
         : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true )
         {
@@ -2050,7 +2059,7 @@ namespace Py
 
         String decode( const char *encoding, const char *error="strict" )
         {
-            return Object( PyString_AsDecodedObject( ptr(), encoding, error ) );
+            return Object( PyString_AsDecodedObject( ptr(), encoding, error ), true );
         }
 
         // Queries
@@ -2148,13 +2157,6 @@ namespace Py
             validate();
         }
 
-        String( const std::string& v, std::string::size_type vsize )
-            : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v.data()),
-                    static_cast<int>( vsize ) ), true)
-        {
-            validate();
-        }
-
         String( const char *v, int vsize )
             : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true )
         {
@@ -2206,17 +2208,17 @@ namespace Py
         {
             if( isUnicode() )
             {
-                return String( PyUnicode_AsEncodedString( ptr(), encoding, error ) );
+                return String( PyUnicode_AsEncodedString( ptr(), encoding, error ), true );
             }
             else
             {
-                return String( PyString_AsEncodedObject( ptr(), encoding, error ) );
+                return String( PyString_AsEncodedObject( ptr(), encoding, error ), true );
             }
         }
 
         String decode( const char *encoding, const char *error="strict" )
         {
-            return Object( PyString_AsDecodedObject( ptr(), encoding, error ) );
+            return Object( PyString_AsDecodedObject( ptr(), encoding, error ), true );
         }
 
         // Queries
@@ -2346,6 +2348,118 @@ namespace Py
 
     };
 
+    class TupleN: public Tuple
+    {
+    public:
+        TupleN()
+        : Tuple( 0 )
+        {
+        }
+
+        TupleN( const Object &obj1 )
+        : Tuple( 1 )
+        {
+            setItem( 0, obj1 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2 )
+        : Tuple( 2 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3 )
+        : Tuple( 3 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4 )
+        : Tuple( 4 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5 )
+        : Tuple( 5 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6 )
+        : Tuple( 6 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6,
+                const Object &obj7 )
+        : Tuple( 7 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+            setItem( 6, obj7 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6,
+                const Object &obj7, const Object &obj8 )
+        : Tuple( 8 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+            setItem( 6, obj7 );
+            setItem( 7, obj8 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6,
+                const Object &obj7, const Object &obj8, const Object &obj9 )
+        : Tuple( 9 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+            setItem( 6, obj7 );
+            setItem( 7, obj8 );
+            setItem( 8, obj9 );
+        }
+
+        virtual ~TupleN()
+        { }
+    };
+
+
     // ==================================================
     // class List
 
@@ -3154,6 +3268,26 @@ namespace Py
         }
     };
 
+    // Call function helper
+    inline Object Object::callMemberFunction( const std::string &function_name ) const
+    {
+        Callable target( getAttr( function_name ) );
+        Tuple args( 0 );
+        return target.apply( args );
+    }
+
+    inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const
+    {
+        Callable target( getAttr( function_name ) );
+        return target.apply( args );
+    }
+
+    inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const
+    {
+        Callable target( getAttr( function_name ) );
+        return target.apply( args, kw );
+    }
+
     // Numeric interface
     inline Object operator+ (const Object& a)
     {
diff --git a/CXX/Python2/PythonType.hxx b/CXX/Python2/PythonType.hxx
diff --git a/CXX/Python2/cxx_extensions.cxx b/CXX/Python2/cxx_extensions.cxx
index 2c39dfd..0e0ade0 100644
--- a/CXX/Python2/cxx_extensions.cxx
+++ b/CXX/Python2/cxx_extensions.cxx
@@ -1320,6 +1320,84 @@ PythonExtensionBase::~PythonExtensionBase()
     assert( ob_refcnt == 0 );
 }
 
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name )
+{
+    Py::TupleN args;
+    return  self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1 )
+{
+    Py::TupleN args( arg1 );
+    return  self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2 )
+{
+    Py::TupleN args( arg1, arg2 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3 )
+{
+    Py::TupleN args( arg1, arg2, arg3 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
+                                            const Py::Object &arg7 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
+                                            const Py::Object &arg7, const Py::Object &arg8 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
+                                            const Py::Object &arg7, const Py::Object &arg8, const Py::Object &arg9 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 );
+    return self().callMemberFunction( fn_name, args );
+}
+
 void PythonExtensionBase::reinit( Tuple &args, Dict &kwds )
 {
     throw RuntimeError( "Must not call __init__ twice on this class" );
@@ -1353,16 +1431,14 @@ int PythonExtensionBase::setattr( const char *, const Py::Object &)
     return -1;
 }
 
-Py::Object PythonExtensionBase::getattro( const Py::String &)
+Py::Object PythonExtensionBase::getattro( const Py::String &name )
 {
-    missing_method( getattro );
-    return Py::None();
+    return genericGetAttro( name );
 }
 
-int PythonExtensionBase::setattro( const Py::String &, const Py::Object &)
+int PythonExtensionBase::setattro( const Py::String &name, const Py::Object &value )
 {
-    missing_method( setattro );
-    return -1;
+    return genericSetAttro( name, value );
 }
 
 int PythonExtensionBase::compare( const Py::Object &)
diff --git a/CXX/Python2/cxxextensions.c b/CXX/Python2/cxxextensions.c
diff --git a/CXX/Python2/cxxsupport.cxx b/CXX/Python2/cxxsupport.cxx
diff --git a/CXX/Python3/Config.hxx b/CXX/Python3/Config.hxx
diff --git a/CXX/Python3/CxxDebug.hxx b/CXX/Python3/CxxDebug.hxx
diff --git a/CXX/Python3/Exception.hxx b/CXX/Python3/Exception.hxx
index 07908d1..0bd052d 100644
--- a/CXX/Python3/Exception.hxx
+++ b/CXX/Python3/Exception.hxx
@@ -164,6 +164,16 @@ namespace Py
         }
     };
     
+    class NotImplementedError: public StandardError
+    {
+    public:
+        NotImplementedError (const std::string& reason)
+            : StandardError()
+        {
+            PyErr_SetString (Py::_Exc_NotImplementedError(), reason.c_str());
+        }
+    };
+    
     class SystemError: public StandardError
     {
     public:
diff --git a/CXX/Python3/ExtensionModule.hxx b/CXX/Python3/ExtensionModule.hxx
diff --git a/CXX/Python3/ExtensionOldType.hxx b/CXX/Python3/ExtensionOldType.hxx
index 56e6af2..b83134f 100644
--- a/CXX/Python3/ExtensionOldType.hxx
+++ b/CXX/Python3/ExtensionOldType.hxx
@@ -74,6 +74,11 @@ namespace Py
             return this;
         }
 
+        Object self()
+        {
+            return asObject( this );
+        }
+
     protected:
         explicit PythonExtension()
         : PythonExtensionBase()
diff --git a/CXX/Python3/ExtensionType.hxx b/CXX/Python3/ExtensionType.hxx
index c1b8721..df680db 100644
--- a/CXX/Python3/ExtensionType.hxx
+++ b/CXX/Python3/ExtensionType.hxx
@@ -45,44 +45,66 @@
 #define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \
     static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \
     { \
-        Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
-        CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
-        Py::Object r( (self->NAME)() ); \
-        return Py::new_reference_to( r.ptr() ); \
+        try \
+        { \
+            Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
+            CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
+            Py::Object r( (self->NAME)() ); \
+            return Py::new_reference_to( r.ptr() ); \
+        } \
+        catch( Py::Exception & ) \
+        { \
+            return 0; \
+        } \
     }
 #define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \
     static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \
     { \
-        Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
-        CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
-        Py::Tuple a( _a ); \
-        Py::Object r( (self->NAME)( a ) ); \
-        return Py::new_reference_to( r.ptr() ); \
+        try \
+        { \
+            Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
+            CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
+            Py::Tuple a( _a ); \
+            Py::Object r( (self->NAME)( a ) ); \
+            return Py::new_reference_to( r.ptr() ); \
+        } \
+        catch( Py::Exception & ) \
+        { \
+            return 0; \
+        } \
     }
 #define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \
     static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \
     { \
-        Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
-        CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
-        Py::Tuple a( _a ); \
-        Py::Dict k; \
-        if( _k != NULL ) \
-            k = _k; \
-        Py::Object r( (self->NAME)( a, k ) ); \
-        return Py::new_reference_to( r.ptr() ); \
+        try \
+        { \
+            Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
+            CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
+            Py::Tuple a( _a ); \
+            Py::Dict k; \
+            if( _k != NULL ) \
+                k = _k; \
+            Py::Object r( (self->NAME)( a, k ) ); \
+            return Py::new_reference_to( r.ptr() ); \
+        } \
+        catch( Py::Exception & ) \
+        { \
+            return 0; \
+        } \
     }
 
 // need to support METH_STATIC and METH_CLASS
 
-#define PYCXX_ADD_NOARGS_METHOD( NAME, docs ) \
-    add_method( #NAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
-#define PYCXX_ADD_VARARGS_METHOD( NAME, docs ) \
-    add_method( #NAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
-#define PYCXX_ADD_KEYWORDS_METHOD( NAME, docs ) \
-    add_method( #NAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
+#define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \
+    add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
+#define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \
+    add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
+#define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \
+    add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
 
 namespace Py
 {
+    extern PythonExtensionBase *getPythonExtensionBase( PyObject *self );
     struct PythonClassInstance
     {
         PyObject_HEAD
@@ -131,7 +153,7 @@ namespace Py
                 {
                     new_mt[ i ] = old_mt[ i ];
                 }
-                delete old_mt;
+                delete[] old_mt;
                 m_methods_table = new_mt;
             }
 
@@ -167,10 +189,8 @@ namespace Py
     protected:
         explicit PythonClass( PythonClassInstance *self, Tuple &args, Dict &kwds )
         : PythonExtensionBase()
-        , m_self( self )
+        , m_class_instance( self )
         {
-            // we are a class
-            behaviors().supportClass();
         }
 
         virtual ~PythonClass()
@@ -203,6 +223,13 @@ namespace Py
                 p->set_tp_new( extension_object_new );
                 p->set_tp_init( extension_object_init );
                 p->set_tp_dealloc( extension_object_deallocator );
+
+                // we are a class
+                p->supportClass();
+
+                // always support get and set attr
+                p->supportGetattro();
+                p->supportSetattro();
             }
 
             return *p;
@@ -238,7 +265,7 @@ namespace Py
                 PythonClassInstance *self = reinterpret_cast<PythonClassInstance *>( _self );
 #ifdef PYCXX_DEBUG
                 std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
-                std::cout << "    self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->cxx_object ) << std::dec << std::endl;
+                std::cout << "    self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
 #endif
 
                 if( self->m_pycxx_object == NULL )
@@ -268,9 +295,10 @@ namespace Py
             PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self );
 #ifdef PYCXX_DEBUG
             std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
-            std::cout << "    self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->cxx_object ) << std::dec << std::endl;
+            std::cout << "    self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
 #endif
             delete self->m_pycxx_object;
+            _self->ob_type->tp_free( _self );
         }
 
     public:
@@ -295,14 +323,19 @@ namespace Py
             return check( ob.ptr() );
         }
 
-        PyObject *selfPtr()
+        virtual PyObject *selfPtr()
+        {
+            return reinterpret_cast<PyObject *>( m_class_instance );
+        }
+
+        virtual Object self()
         {
-            return reinterpret_cast<PyObject *>( m_self );
+            return Object( reinterpret_cast<PyObject *>( m_class_instance ) );
         }
 
     protected:
     private:
-        PythonClassInstance *m_self;
+        PythonClassInstance *m_class_instance;
 
     private:
         //
@@ -361,7 +394,7 @@ namespace Py
         //
         T *getCxxObject( void )
         {
-            return static_cast<T *>( ptr() );
+            return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) );
         }
     };
 } // Namespace Py
diff --git a/CXX/Python3/ExtensionTypeBase.hxx b/CXX/Python3/ExtensionTypeBase.hxx
index 258d61f..8bd65eb 100644
--- a/CXX/Python3/ExtensionTypeBase.hxx
+++ b/CXX/Python3/ExtensionTypeBase.hxx
@@ -124,7 +124,39 @@ namespace Py
         // QQQ need to add py3 interface
 
     public:
+        // helper functions to call function fn_name with 0 to 9 args
+        Object callOnSelf( const std::string &fn_name );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6,
+                                const Object &arg7 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6,
+                                const Object &arg7, const Object &arg8 );
+        Object callOnSelf( const std::string &fn_name,
+                                const Object &arg1, const Object &arg2, const Object &arg3,
+                                const Object &arg4, const Object &arg5, const Object &arg6,
+                                const Object &arg7, const Object &arg8, const Object &arg9 );
+
+    public:
         virtual PyObject *selfPtr() = 0;
+        virtual Object self() = 0;
 
     private:
         void missing_method( void );
diff --git a/CXX/Python3/Extensions.hxx b/CXX/Python3/Extensions.hxx
diff --git a/CXX/Python3/IndirectPythonInterface.hxx b/CXX/Python3/IndirectPythonInterface.hxx
index fed8e3c..fb97b72 100644
--- a/CXX/Python3/IndirectPythonInterface.hxx
+++ b/CXX/Python3/IndirectPythonInterface.hxx
@@ -78,8 +78,6 @@ PyObject * _Exc_ZeroDivisionError();
 PyObject * _Exc_WindowsError();
 #endif
 
-PyObject * _Exc_MemoryErrorInst();
-
 PyObject * _Exc_IndentationError();
 PyObject * _Exc_TabError();
 PyObject * _Exc_UnboundLocalError();
diff --git a/CXX/Python3/Objects.hxx b/CXX/Python3/Objects.hxx
index a991bb8..bf1408c 100644
--- a/CXX/Python3/Objects.hxx
+++ b/CXX/Python3/Objects.hxx
@@ -63,6 +63,8 @@ namespace Py
     class String;
     class List;
     template<TEMPLATE_TYPENAME T> class MapBase;
+    class Tuple;
+    class Dict;
 
     //===========================================================================//
     // class Object
@@ -265,6 +267,10 @@ namespace Py
             return Object( PyObject_GetAttrString( p, const_cast<char*>( s.c_str() ) ), true );
         }
 
+        Object callMemberFunction( const std::string &function_name ) const;
+        Object callMemberFunction( const std::string &function_name, const Tuple &args ) const;
+        Object callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const;
+
         Object getItem( const Object &key ) const
         {
             return Object( PyObject_GetItem( p, *key ), true );
@@ -1322,7 +1328,6 @@ namespace Py
         }
 
         // Assignment acquires new ownership of pointer
-
         SeqBase<T> &operator=( const Object &rhs )
         {
             return *this = *rhs;
@@ -2012,7 +2017,7 @@ namespace Py
         }
 
         String()
-        : SeqBase<Char>( PyUnicode_FromString( "" ), true )
+        : SeqBase<Char>( PyUnicode_FromString( "" ) )
         {
             validate();
         }
@@ -2053,19 +2058,25 @@ namespace Py
 
         */
         String( const std::string &s, const char *encoding, const char *errors=NULL )
-        : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.size(), encoding, errors ) )
+        : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.size(), encoding, errors ), true )
         {
             validate();
         }
 
         String( const char *s, const char *encoding, const char *errors=NULL )
-        : SeqBase<Char>( PyUnicode_Decode( s, strlen(s), encoding, errors ) )
+        : SeqBase<Char>( PyUnicode_Decode( s, strlen(s), encoding, errors ), true )
         {
             validate();
         }
 
         String( const char *s, Py_ssize_t size, const char *encoding, const char *errors=NULL )
-        : SeqBase<Char>( PyUnicode_Decode( s, size, encoding, errors ) )
+        : SeqBase<Char>( PyUnicode_Decode( s, size, encoding, errors ), true )
+        {
+            validate();
+        }
+
+        String( const Py_UNICODE *s, int length )
+        : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true )
         {
             validate();
         }
@@ -2092,7 +2103,7 @@ namespace Py
         // Encode
         Bytes encode( const char *encoding, const char *error="strict" ) const
         {
-            return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ) );
+            return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ), true );
         }
 
         // Queries
@@ -2117,6 +2128,11 @@ namespace Py
             Bytes b( encode( encoding, error ) );
             return b.as_std_string();
         }
+
+        const Py_UNICODE *unicode_data() const
+        {
+            return PyUnicode_AS_UNICODE( ptr() );
+        }
     };
 
     // ==================================================
@@ -2175,8 +2191,8 @@ namespace Py
                 }
             }
         }
-        // Assignment acquires new ownership of pointer
 
+        // Assignment acquires new ownership of pointer
         Tuple &operator=( const Object &rhs )
         {
             return *this = *rhs;
@@ -2201,6 +2217,117 @@ namespace Py
 
     };
 
+    class TupleN: public Tuple
+    {
+    public:
+        TupleN()
+        : Tuple( 0 )
+        {
+        }
+
+        TupleN( const Object &obj1 )
+        : Tuple( 1 )
+        {
+            setItem( 0, obj1 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2 )
+        : Tuple( 2 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3 )
+        : Tuple( 3 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4 )
+        : Tuple( 4 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5 )
+        : Tuple( 5 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6 )
+        : Tuple( 6 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6,
+                const Object &obj7 )
+        : Tuple( 7 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+            setItem( 6, obj7 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6,
+                const Object &obj7, const Object &obj8 )
+        : Tuple( 8 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+            setItem( 6, obj7 );
+            setItem( 7, obj8 );
+        }
+
+        TupleN( const Object &obj1, const Object &obj2, const Object &obj3,
+                const Object &obj4, const Object &obj5, const Object &obj6,
+                const Object &obj7, const Object &obj8, const Object &obj9 )
+        : Tuple( 9 )
+        {
+            setItem( 0, obj1 );
+            setItem( 1, obj2 );
+            setItem( 2, obj3 );
+            setItem( 3, obj4 );
+            setItem( 4, obj5 );
+            setItem( 5, obj6 );
+            setItem( 6, obj7 );
+            setItem( 7, obj8 );
+            setItem( 8, obj9 );
+        }
+
+        virtual ~TupleN()
+        { }
+    };
+
     // ==================================================
     // class List
 
@@ -2252,8 +2379,8 @@ namespace Py
         {
             return max_size();
         }
-        // Assignment acquires new ownership of pointer
 
+        // Assignment acquires new ownership of pointer
         List &operator=( const Object &rhs )
         {
             return *this = *rhs;
@@ -2946,8 +3073,8 @@ namespace Py
             set( PyDict_New(), true );
             validate();
         }
-        // Assignment acquires new ownership of pointer
 
+        // Assignment acquires new ownership of pointer
         Dict &operator=( const Object &rhs )
         {
             return *this = *rhs;
@@ -3067,6 +3194,26 @@ namespace Py
         }
     };
 
+    // Call function helper
+    inline Object Object::callMemberFunction( const std::string &function_name ) const
+    {
+        Callable target( getAttr( function_name ) );
+        Tuple args( 0 );
+        return target.apply( args );
+    }
+
+    inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const
+    {
+        Callable target( getAttr( function_name ) );
+        return target.apply( args );
+    }
+
+    inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const
+    {
+        Callable target( getAttr( function_name ) );
+        return target.apply( args, kw );
+    }
+
     // Numeric interface
     inline Object operator+( const Object &a )
     {
diff --git a/CXX/Python3/PythonType.hxx b/CXX/Python3/PythonType.hxx
diff --git a/CXX/Python3/cxx_extensions.cxx b/CXX/Python3/cxx_extensions.cxx
index 0e07216..9f26166 100644
--- a/CXX/Python3/cxx_extensions.cxx
+++ b/CXX/Python3/cxx_extensions.cxx
@@ -1118,6 +1118,84 @@ PythonExtensionBase::~PythonExtensionBase()
     assert( ob_refcnt == 0 );
 }
 
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name )
+{
+    Py::TupleN args;
+    return  self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1 )
+{
+    Py::TupleN args( arg1 );
+    return  self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2 )
+{
+    Py::TupleN args( arg1, arg2 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3 )
+{
+    Py::TupleN args( arg1, arg2, arg3 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
+                                            const Py::Object &arg7 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
+                                            const Py::Object &arg7, const Py::Object &arg8 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 );
+    return self().callMemberFunction( fn_name, args );
+}
+
+Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name,
+                                            const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3,
+                                            const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6,
+                                            const Py::Object &arg7, const Py::Object &arg8, const Py::Object &arg9 )
+{
+    Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 );
+    return self().callMemberFunction( fn_name, args );
+}
+
 void PythonExtensionBase::reinit( Tuple &args, Dict &kwds )
 {
     throw RuntimeError( "Must not call __init__ twice on this class" );
@@ -1154,16 +1232,14 @@ int PythonExtensionBase::setattr( const char *, const Py::Object & )
     return -1;
 }
 
-Py::Object PythonExtensionBase::getattro( const Py::String & )
+Py::Object PythonExtensionBase::getattro( const Py::String &name )
 {
-    missing_method( getattro );
-    return Py::None();
+    return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) );
 }
 
-int PythonExtensionBase::setattro( const Py::String &, const Py::Object & )
+int PythonExtensionBase::setattro( const Py::String &name, const Py::Object &value )
 {
-    missing_method( setattro );
-    return -1;
+    return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() );
 }
 
 
diff --git a/CXX/Python3/cxxextensions.c b/CXX/Python3/cxxextensions.c
diff --git a/CXX/Python3/cxxsupport.cxx b/CXX/Python3/cxxsupport.cxx
diff --git a/CXX/Version.hxx b/CXX/Version.hxx
index 398889c..c6c5c63 100644
--- a/CXX/Version.hxx
+++ b/CXX/Version.hxx
@@ -39,8 +39,8 @@
 #define __PyCXX_version_hxx__
 
 #define PYCXX_VERSION_MAJOR 6
-#define PYCXX_VERSION_MINOR 1
-#define PYCXX_VERSION_PATCH 1
+#define PYCXX_VERSION_MINOR 2
+#define PYCXX_VERSION_PATCH 3
 #define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch))
 #define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH )
 #endif
diff --git a/CXX/WrapPython.h b/CXX/WrapPython.h
index f62d5b4..118a874 100644
--- a/CXX/WrapPython.h
+++ b/CXX/WrapPython.h
@@ -38,12 +38,23 @@
 #ifndef __PyCXX_wrap_python_hxx__
 #define __PyCXX_wrap_python_hxx__
 
-/* Python API mandates Python.h is included *first* */
-#include "Python.h"
-
 // On some platforms we have to include time.h to get select defined
 #if !defined(__WIN32__) && !defined(WIN32) && !defined(_WIN32) && !defined(_WIN64)
 #include <sys/time.h>
 #endif
 
+// Prevent multiple conflicting definitions of swab from stdlib.h and unistd.h
+#if defined(__sun) || defined(sun)
+#if defined(_XPG4)
+#undef _XPG4
+#endif
+#endif
+
+// Python.h will redefine these and generate warning in the process
+#undef _XOPEN_SOURCE
+#undef _POSIX_C_SOURCE
+
+// pull in python definitions
+#include <Python.h>
+
 #endif
diff --git a/CXX/cxx_extensions.cxx b/CXX/cxx_extensions.cxx
diff --git a/CXX/cxxextensions.c b/CXX/cxxextensions.c
index cfab556..efed5d5 100644
--- a/CXX/cxxextensions.c
+++ b/CXX/cxxextensions.c
@@ -37,7 +37,7 @@
 #include "CXX/WrapPython.h"
 
 #if PY_MAJOR_VERSION == 2
-#include "Python2/cxxextensions.c"
+#include "CXX/Python2/cxxextensions.c"
 #else
-#include "Python3/cxxextensions.c"
+#include "CXX/Python3/cxxextensions.c"
 #endif
diff --git a/CXX/cxxsupport.cxx b/CXX/cxxsupport.cxx
index 946e60d..e96b9c9 100644
--- a/CXX/cxxsupport.cxx
+++ b/CXX/cxxsupport.cxx
@@ -37,7 +37,7 @@
 #include "CXX/WrapPython.h"
 
 #if PY_MAJOR_VERSION == 2
-#include "Python2/cxxsupport.cxx"
+#include "CXX/Python2/cxxsupport.cxx"
 #else
-#include "Python3/cxxsupport.cxx"
+#include "CXX/Python3/cxxsupport.cxx"
 #endif
diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py
index 5bfb8e9..18a49aa 100644
--- a/lib/matplotlib/patches.py
+++ b/lib/matplotlib/patches.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
 from __future__ import division
 import math
 
diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py
index a355dd3..ccc3f31 100644
--- a/lib/mpl_toolkits/mplot3d/art3d.py
+++ b/lib/mpl_toolkits/mplot3d/art3d.py
@@ -439,7 +439,7 @@ class Poly3DCollection(PolyCollection):
         if self._zsort:
             z_segments_2d = [(self._zsortfunc(zs), zip(xs, ys), fc, ec) for
                     (xs, ys, zs), fc, ec in zip(xyzlist, cface, cedge)]
-            z_segments_2d.sort(cmp=lambda x, y: cmp(y[0], x[0]))
+            z_segments_2d.sort(key=lambda x: x[0])
         else:
             raise ValueError, "whoops"
 
diff --git a/setupext.py b/setupext.py
index 957febf..3e76f09 100644
--- a/setupext.py
+++ b/setupext.py
@@ -925,7 +925,7 @@ def add_tk_flags(module):
     message = None
     if sys.platform == 'win32':
         major, minor1, minor2, s, tmp = sys.version_info
-        if major == 2 and minor1 in [6, 7]:
+        if (major == 2 and minor1 in [6, 7]) or (major == 3 and minor1 in [1, 2]):
             module.include_dirs.extend(['win32_static/include/tcl85'])
             module.libraries.extend(['tk85', 'tcl85'])
         elif major == 2 and minor1 in [3, 4, 5]:
diff --git a/src/_windowing.cpp b/src/_windowing.cpp
index 949944c..baf59b1 100644
--- a/src/_windowing.cpp
+++ b/src/_windowing.cpp
@@ -1,5 +1,3 @@
-/* -*- mode: c++; c-basic-offset: 4 -*- */
-
 #include "Python.h"
 #include <windows.h>
 
@@ -11,7 +9,11 @@ _GetForegroundWindow(PyObject *module, PyObject *args)
     {
         return NULL;
     }
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong((long) handle);
+#else
     return PyInt_FromLong((long) handle);
+#endif
 }
 
 static PyObject *
@@ -38,7 +40,29 @@ static PyMethodDef _windowing_methods[] =
     {NULL, NULL}
 };
 
-extern "C" DL_EXPORT(void) init_windowing()
+#if PY_MAJOR_VERSION >= 3
+
+static struct PyModuleDef moduledef = {
+        PyModuleDef_HEAD_INIT,
+        "_windowing",
+        NULL,
+        NULL,
+        _windowing_methods,
+        NULL,
+        NULL,
+        NULL,
+        NULL
+};
+
+PyMODINIT_FUNC PyInit__windowing(void)
+{
+    PyObject *module = PyModule_Create(&moduledef);
+    return module;
+}
+
+#else
+PyMODINIT_FUNC init_windowing()
 {
     Py_InitModule("_windowing", _windowing_methods);
 }
+#endif
diff --git a/src/ft2font.cpp b/src/ft2font.cpp
index 9807905..dd10367 100644
--- a/src/ft2font.cpp
+++ b/src/ft2font.cpp
@@ -2121,7 +2121,7 @@ char ft2font_new__doc__[] =
     "  postscript_name        PostScript name of the font\n"
     ;
 
-#if defined(_MSC_VER)
+#if defined(_MSC_VER1)
 DL_EXPORT(void)
 #elif defined(__cplusplus)
 extern "C"
