diff --git a/CXX/Python2/Config.hxx b/CXX/Python2/Config.hxx
index b27f9ba..10fc2c3 100644
--- a/CXX/Python2/Config.hxx
+++ b/CXX/Python2/Config.hxx
@@ -53,7 +53,7 @@
 #endif
 
 //
-//	Assume all other compilers do
+// Assume all other compilers do
 //
 #else
 
@@ -68,7 +68,7 @@
 #endif
 
 //
-//	Which C++ standard is in use?
+// Which C++ standard is in use?
 //
 #if defined( _MSC_VER )
 #  if _MSC_VER <= 1200
diff --git a/CXX/Python2/ExtensionType.hxx b/CXX/Python2/ExtensionType.hxx
index 7145bd0..773c198 100644
--- a/CXX/Python2/ExtensionType.hxx
+++ b/CXX/Python2/ExtensionType.hxx
@@ -201,7 +201,7 @@ namespace Py
         }
 
         virtual ~PythonClass()
-        {} 
+        {}
 
         static ExtensionClassMethodsTable &methodTable()
         {
@@ -219,7 +219,7 @@ namespace Py
         static PythonType &behaviors()
         {
             static PythonType *p;
-            if( p == NULL ) 
+            if( p == NULL )
             {
 #if defined( _CPPRTTI ) || defined( __GNUG__ )
                 const char *default_name = (typeid( T )).name();
@@ -330,7 +330,7 @@ namespace Py
                     return false;
                 case 1:
                     return true;
-            }            
+            }
         }
 
         static bool check( const Object &ob )
diff --git a/CXX/Python2/ExtensionTypeBase.hxx b/CXX/Python2/ExtensionTypeBase.hxx
index 237ae78..03161b6 100644
--- a/CXX/Python2/ExtensionTypeBase.hxx
+++ b/CXX/Python2/ExtensionTypeBase.hxx
@@ -47,14 +47,14 @@ namespace Py
     // There are two ways that extension objects can get destroyed.
     // 1. Their reference count goes to zero
     // 2. Someone does an explicit delete on a pointer.
-    // In(1) the problem is to get the destructor called 
+    // In(1) the problem is to get the destructor called
     //      We register a special deallocator in the Python type object
     //      (see behaviors()) to do this.
     // In(2) there is no problem, the dtor gets called.
 
-    // PythonExtension does not use the usual Python heap allocator, 
+    // PythonExtension does not use the usual Python heap allocator,
     // instead using new/delete. We do the setting of the type object
-    // and reference count, usually done by PyObject_New, in the 
+    // and reference count, usually done by PyObject_New, in the
     // base class ctor.
 
     // This special deallocator does a delete on the pointer.
@@ -66,7 +66,7 @@ namespace Py
         virtual ~PythonExtensionBase();
 
     public:
-        // object 
+        // object
         virtual void reinit( Tuple &args, Dict &kwds );
 
         // object basics
diff --git a/CXX/Python2/Objects.hxx b/CXX/Python2/Objects.hxx
index e453fcd..2b572e3 100644
--- a/CXX/Python2/Objects.hxx
+++ b/CXX/Python2/Objects.hxx
@@ -1858,7 +1858,7 @@ 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);
     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); 
+    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);
@@ -1872,7 +1872,7 @@ namespace Py
     extern bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right);
     extern bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right);
     extern bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right);
-    extern bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); 
+    extern bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right);
 
     // ==================================================
     // class Char
diff --git a/CXX/Python2/PythonType.hxx b/CXX/Python2/PythonType.hxx
index 7f26d87..8b1b54f 100644
--- a/CXX/Python2/PythonType.hxx
+++ b/CXX/Python2/PythonType.hxx
@@ -44,7 +44,7 @@ namespace Py
     {
     public:
 #define B(n) (1<<(n))
-        // if you define one sequence method you must define 
+        // if you define one sequence method you must define
         // all of them except the assigns
 
         PythonType( size_t base_size, int itemsize, const char *default_name );
@@ -161,7 +161,7 @@ namespace Py
                         support_number_oct |
                         support_number_hex
                         );
- 
+
         enum {
             support_buffer_getreadbuffer =      B(0),
             support_buffer_getwritebuffer =     B(1),
diff --git a/CXX/Python3/Config.hxx b/CXX/Python3/Config.hxx
index 25fb1d4..490c9ae 100644
--- a/CXX/Python3/Config.hxx
+++ b/CXX/Python3/Config.hxx
@@ -57,7 +57,7 @@
 #endif
 
 //
-//	Assume all other compilers do
+// Assume all other compilers do
 //
 #else
 
@@ -72,7 +72,7 @@
 #endif
 
 //
-//	Which C++ standard is in use?
+// Which C++ standard is in use?
 //
 #if defined( _MSC_VER )
 #  if _MSC_VER <= 1200
diff --git a/CXX/Python3/ExtensionType.hxx b/CXX/Python3/ExtensionType.hxx
index 6fd7fea..084a9b8 100644
--- a/CXX/Python3/ExtensionType.hxx
+++ b/CXX/Python3/ExtensionType.hxx
@@ -200,7 +200,7 @@ namespace Py
         }
 
         virtual ~PythonClass()
-        {} 
+        {}
 
         static ExtensionClassMethodsTable &methodTable()
         {
@@ -218,7 +218,7 @@ namespace Py
         static PythonType &behaviors()
         {
             static PythonType *p;
-            if( p == NULL ) 
+            if( p == NULL )
             {
 #if defined( _CPPRTTI ) || defined( __GNUG__ )
                 const char *default_name = (typeid( T )).name();
@@ -340,7 +340,7 @@ namespace Py
                     return false;
                 case 1:
                     return true;
-            }            
+            }
         }
 
         static bool check( const Object &ob )
diff --git a/CXX/Python3/ExtensionTypeBase.hxx b/CXX/Python3/ExtensionTypeBase.hxx
index 81417dd..9313c1b 100644
--- a/CXX/Python3/ExtensionTypeBase.hxx
+++ b/CXX/Python3/ExtensionTypeBase.hxx
@@ -47,14 +47,14 @@ namespace Py
     // There are two ways that extension objects can get destroyed.
     // 1. Their reference count goes to zero
     // 2. Someone does an explicit delete on a pointer.
-    // In(1) the problem is to get the destructor called 
+    // In(1) the problem is to get the destructor called
     //      We register a special deallocator in the Python type object
     //      (see behaviors()) to do this.
     // In(2) there is no problem, the dtor gets called.
 
-    // PythonExtension does not use the usual Python heap allocator, 
+    // PythonExtension does not use the usual Python heap allocator,
     // instead using new/delete. We do the setting of the type object
-    // and reference count, usually done by PyObject_New, in the 
+    // and reference count, usually done by PyObject_New, in the
     // base class ctor.
 
     // This special deallocator does a delete on the pointer.
@@ -66,7 +66,7 @@ namespace Py
         virtual ~PythonExtensionBase();
 
     public:
-        // object 
+        // object
         virtual void reinit( Tuple &args, Dict &kwds );
 
         // object basics
@@ -114,7 +114,6 @@ namespace Py
         virtual Object number_invert();
         virtual Object number_int();
         virtual Object number_float();
-        virtual Object number_long();
         virtual Object number_add( const Object & );
         virtual Object number_subtract( const Object & );
         virtual Object number_multiply( const Object & );
@@ -126,6 +125,28 @@ namespace Py
         virtual Object number_xor( const Object & );
         virtual Object number_or( const Object & );
         virtual Object number_power( const Object &, const Object & );
+        virtual Object number_floor_divide( const Object & );
+        virtual Object number_true_divide( const Object & );
+        virtual Object number_index();
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+        virtual Object number_matrix_multiply( const Object & );
+#endif
+
+        virtual Object number_inplace_add( const Object & );
+        virtual Object number_inplace_subtract( const Object & );
+        virtual Object number_inplace_multiply( const Object & );
+        virtual Object number_inplace_remainder( const Object & );
+        virtual Object number_inplace_power( const Object &, const Object & );
+        virtual Object number_inplace_lshift( const Object & );
+        virtual Object number_inplace_rshift( const Object & );
+        virtual Object number_inplace_and( const Object & );
+        virtual Object number_inplace_xor( const Object & );
+        virtual Object number_inplace_or( const Object & );
+        virtual Object number_inplace_floor_divide( const Object & );
+        virtual Object number_inplace_true_divide( const Object & );
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+        virtual Object number_inplace_matrix_multiply( const Object & );
+#endif
 
 #if !defined( Py_LIMITED_API )
         // Buffer
diff --git a/CXX/Python3/Objects.hxx b/CXX/Python3/Objects.hxx
index 34ca7a2..4d53a8d 100644
--- a/CXX/Python3/Objects.hxx
+++ b/CXX/Python3/Objects.hxx
@@ -51,6 +51,7 @@
 #include <utility>
 #include <typeinfo>
 #include <algorithm>
+#include <cstring>
 
 namespace Py
 {
@@ -1737,7 +1738,7 @@ 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 );
     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 ); 
+    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 );
@@ -1752,7 +1753,7 @@ namespace Py
     extern bool operator< ( const Sequence::const_iterator &left, const Sequence::const_iterator &right );
     extern bool operator> ( const Sequence::const_iterator &left, const Sequence::const_iterator &right );
     extern bool operator<=( const Sequence::const_iterator &left, const Sequence::const_iterator &right );
-    extern bool operator>=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); 
+    extern bool operator>=( const Sequence::const_iterator &left, const Sequence::const_iterator &right );
 
     // ==================================================
     // class Char
@@ -1965,7 +1966,7 @@ namespace Py
 
 #if !defined( Py_LIMITED_API )
         Char( const unicodestring &v )
-        : Object( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ),1 ), true )
+        : Object( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, const_cast<Py_UNICODE*>( v.data() ),1 ), true )
         {
             validate();
         }
@@ -1987,7 +1988,7 @@ namespace Py
 #if !defined( Py_LIMITED_API )
         Char &operator=( const unicodestring &v )
         {
-            set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), 1 ), true );
+            set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, const_cast<Py_UNICODE*>( v.data() ), 1 ), true );
             return *this;
         }
 #endif
@@ -1996,7 +1997,7 @@ namespace Py
         Char &operator=( int v_ )
         {
             Py_UNICODE v( static_cast<Py_UNICODE>( v_ ) );
-            set( PyUnicode_FromUnicode( &v, 1 ), true );
+            set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, &v, 1 ), true );
             return *this;
         }
 #endif
@@ -2004,7 +2005,7 @@ namespace Py
 #if !defined( Py_LIMITED_API )
         Char &operator=( Py_UNICODE v )
         {
-            set( PyUnicode_FromUnicode( &v, 1 ), true );
+            set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, &v, 1 ), true );
             return *this;
         }
 #endif
@@ -2093,7 +2094,7 @@ namespace Py
 
            Many of these APIs take two arguments encoding and errors. These
            parameters encoding and errors have the same semantics as the ones
-           of the builtin unicode() API. 
+           of the builtin unicode() API.
 
            Setting encoding to NULL causes the default encoding to be used.
 
@@ -2142,7 +2143,7 @@ namespace Py
 
 #if !defined( Py_LIMITED_API )
         String( const Py_UNICODE *s, int length )
-        : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true )
+        : SeqBase<Char>( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, s, length ), true )
         {
             validate();
         }
@@ -2164,7 +2165,7 @@ namespace Py
 #if !defined( Py_LIMITED_API )
         String &operator=( const unicodestring &v )
         {
-            set( PyUnicode_FromUnicode( const_cast<Py_UNICODE *>( v.data() ), v.length() ), true );
+            set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, const_cast<Py_UNICODE *>( v.data() ), v.length() ), true );
             return *this;
         }
 #endif
@@ -2190,6 +2191,7 @@ namespace Py
         }
 #endif
 
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9
 #if !defined( Py_LIMITED_API )
         const Py_UNICODE *unicode_data() const
         {
@@ -2203,6 +2205,8 @@ namespace Py
             return unicodestring( unicode_data(), PyUnicode_GetLength( ptr() ) );
         }
 #endif
+#endif
+
         ucs4string as_ucs4string() const
         {
             Py_UCS4 *buf = new Py_UCS4[ size() ];
@@ -2999,7 +3003,7 @@ namespace Py
 
             // postfix --
             iterator operator--( int )
-            { 
+            {
                 return iterator( map, keys, pos-- );
             }
 
@@ -3242,14 +3246,36 @@ namespace Py
         // Call with keywords
         Object apply( const Tuple &args, const Dict &kw ) const
         {
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 9
+            PyObject *result = PyObject_Call( ptr(), args.ptr(), kw.ptr() );
+#else
             PyObject *result = PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() );
+#endif
             if( result == NULL )
             {
                 ifPyErrorThrowCxxException();
             }
             return asObject( result );
         }
+#if (!defined( Py_LIMITED_API ) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 9) || (defined( Py_LIMITED_API ) && Py_LIMITED_API+0 >= 0x03090000)
+        Object apply() const
+        {
+            PyObject *result = PyObject_CallNoArgs( ptr() );
+            return asObject( result );
+        }
 
+        Object apply( PyObject *pargs ) const
+        {
+            if( pargs == 0 )
+            {
+                return apply( Tuple() );
+            }
+            else
+            {
+                return apply( Tuple( pargs ) );
+            }
+        }
+#else
         Object apply( PyObject *pargs = 0 ) const
         {
             if( pargs == 0 )
@@ -3261,6 +3287,7 @@ namespace Py
                 return apply( Tuple( pargs ) );
             }
         }
+#endif
     };
 
     class Module: public Object
@@ -3311,8 +3338,7 @@ namespace Py
     inline Object Object::callMemberFunction( const std::string &function_name ) const
     {
         Callable target( getAttr( function_name ) );
-        Tuple args( 0 );
-        return target.apply( args );
+        return target.apply();
     }
 
     inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const
diff --git a/CXX/Python3/PythonType.hxx b/CXX/Python3/PythonType.hxx
index 274d53d..4640866 100644
--- a/CXX/Python3/PythonType.hxx
+++ b/CXX/Python3/PythonType.hxx
@@ -47,7 +47,7 @@ namespace Py
     class PythonType
     {
     public:
-        // if you define one sequence method you must define 
+        // if you define one sequence method you must define
         // all of them except the assigns
 
         PythonType( size_t base_size, int itemsize, const char *default_name );
@@ -133,27 +133,54 @@ namespace Py
             support_number_xor =                B(13),
             support_number_or =                 B(14),
             support_number_int =                B(15),
-            support_number_float=               B(16)
+            support_number_float =              B(16),
+            support_number_floor_divide =       B(17),
+            support_number_true_divide =        B(18),
+            support_number_index =              B(19),
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+            support_number_matrix_multiply =    B(20),
+#endif
+
+            // start a new bit mask for inplace that avoid using more then 32 bits in methods_to_support
+            support_number_inplace_floor_divide = B(0),
+            support_number_inplace_true_divide = B(1),
+            support_number_inplace_add =        B(2),
+            support_number_inplace_subtract =   B(3),
+            support_number_inplace_multiply =   B(4),
+            support_number_inplace_remainder =  B(5),
+            support_number_inplace_power =      B(6),
+            support_number_inplace_lshift =     B(7),
+            support_number_inplace_rshift =     B(8),
+            support_number_inplace_and =        B(9),
+            support_number_inplace_xor =        B(10),
+            support_number_inplace_or =         B(11)
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+            ,
+            support_number_inplace_matrix_multiply = B(12)
+#endif
         };
-        PythonType &supportNumberType( int methods_to_support=
-                    support_number_add |
-                    support_number_subtract |
-                    support_number_multiply |
-                    support_number_remainder |
-                    support_number_divmod |
-                    support_number_power |
-                    support_number_negative |
-                    support_number_positive |
-                    support_number_absolute |
-                    support_number_invert |
-                    support_number_lshift |
-                    support_number_rshift |
-                    support_number_and |
-                    support_number_xor |
-                    support_number_or |
-                    support_number_int |
-                    support_number_float
-                    );
+        PythonType &supportNumberType(
+            int methods_to_support=
+                support_number_add |
+                support_number_subtract |
+                support_number_multiply |
+                support_number_remainder |
+                support_number_divmod |
+                support_number_power |
+                support_number_negative |
+                support_number_positive |
+                support_number_absolute |
+                support_number_invert |
+                support_number_lshift |
+                support_number_rshift |
+                support_number_and |
+                support_number_xor |
+                support_number_or |
+                support_number_int |
+                support_number_float,
+            int inplace_methods_to_support=0
+            );
+
 #if !defined( Py_LIMITED_API )
         enum {
             support_buffer_getbuffer =          B(0),
diff --git a/CXX/Version.hxx b/CXX/Version.hxx
index 57452c3..e6069aa 100644
--- a/CXX/Version.hxx
+++ b/CXX/Version.hxx
@@ -40,7 +40,7 @@
 
 #define PYCXX_VERSION_MAJOR 7
 #define PYCXX_VERSION_MINOR 1
-#define PYCXX_VERSION_PATCH 3
+#define PYCXX_VERSION_PATCH 7
 #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/Demo/Python2/example.cxx b/Demo/Python2/example.cxx
index 4eef1b9..d936822 100644
--- a/Demo/Python2/example.cxx
+++ b/Demo/Python2/example.cxx
@@ -236,7 +236,7 @@ test_numbers()
     return "ok";
 }
 
-static std::string 
+static std::string
 test_List_iterators (const Py::List& x, Py::List& y)
 {
     std::vector<Py::Object> v;
@@ -275,7 +275,7 @@ test_List_iterators (const Py::List& x, Py::List& y)
     {
         std::cout << "About to raise exception int(\"Howdy\")" << std::endl;
         o2 = o1;
-    } 
+    }
     catch (Py::BaseException &e)
     {
         std::cout << "Catch o.k." << std::endl;
@@ -317,7 +317,7 @@ test_List()
     a.append(i);
     a.append(x);
     a.append(Py::Float(0.0));
-    b = a[0]; 
+    b = a[0];
     a[2] = b;
     a.append(c+d);
     a.append(aux);
@@ -332,7 +332,7 @@ test_List()
     Py::List::iterator l1, l2;
     for(l1= a.begin(), l2 = ans.begin();
         l1 != a.end() && l2 != ans.end();
-        ++l1, ++l2) 
+        ++l1, ++l2)
     {
         if(*l1 != *l2) return "failed 1" + a.as_string();
     }
@@ -436,7 +436,7 @@ test_Tuple()
     return "ok";
 }
 
-static std::string 
+static std::string
 test_STL()
 {
     int ans1;
@@ -508,7 +508,7 @@ void debug_check_ref_queue()
         p_slow = p_slow->_ob_next;
         p_fast = p_slow->_ob_next->_ob_next;
 
-        assert( p_slow != p_fast );    
+        assert( p_slow != p_fast );
     }
     while( p_slow != list_element.ptr() );
 
@@ -623,7 +623,7 @@ private:
 
         Py::Float f(0.0);
         for( Py::Sequence::size_type i = 0; i < a.length(); i++ )
-        {    
+        {
             Py::Float g (a[i]);
             f = f + g;
         }
@@ -631,7 +631,7 @@ private:
         return f;
     }
 
-    Py::Object ex_test( const Py::Tuple &a) 
+    Py::Object ex_test( const Py::Tuple &a)
     {
         debug_check_ref_queue();
 
diff --git a/Demo/Python2/pycxx_iter.cxx b/Demo/Python2/pycxx_iter.cxx
index 22a71c4..1bcc755 100644
--- a/Demo/Python2/pycxx_iter.cxx
+++ b/Demo/Python2/pycxx_iter.cxx
@@ -24,7 +24,7 @@ public:
         add_varargs_method("IterT",&MyIterModule::new_IterT,"IterT(from,last)");
         initialize("MyIterModule documentation"); // register with Python
     }
-    
+
     virtual ~MyIterModule() {}
 
 private:
diff --git a/Demo/Python2/pycxx_iter.hxx b/Demo/Python2/pycxx_iter.hxx
index 2ce96cf..7f10591 100644
--- a/Demo/Python2/pycxx_iter.hxx
+++ b/Demo/Python2/pycxx_iter.hxx
@@ -3,7 +3,7 @@
 #include <sstream>
 #include <string>
 
-class IterT : public Py::PythonExtension<IterT> 
+class IterT : public Py::PythonExtension<IterT>
 {
     int from, count, last;
     int fwd_iter;
@@ -43,7 +43,7 @@ public:
             fwd_iter = 1;    // indicate forward iteration
         return Py::Object(this,false);    // increment the refcount
     }
-    
+
     PyObject* iternext()
     {
         int ct;
@@ -58,7 +58,7 @@ public:
                     fwd_iter=2;
                 }
             else if( count <= last )
-                ct= count++; 
+                ct= count++;
             else
                 return NULL;    // signal StopIteration
         }
diff --git a/Demo/Python2/range.cxx b/Demo/Python2/range.cxx
index 442e802..f9d4335 100644
--- a/Demo/Python2/range.cxx
+++ b/Demo/Python2/range.cxx
@@ -55,7 +55,7 @@ Py_ssize_t range::sequence_length()
     return length();
 }
 
-Py::Object range::sequence_item( Py_ssize_t i ) 
+Py::Object range::sequence_item( Py_ssize_t i )
 {
     return Py::Int( item( static_cast<int>( i ) ) );
 }
@@ -83,7 +83,7 @@ Py::Object range::getattr( const char *name )
 }
 
 // "regular" methods...
-Py::Object range::amethod( const Py::Tuple &t ) 
+Py::Object range::amethod( const Py::Tuple &t )
 {
     t.verify_length(1);
     Py::List result;
@@ -98,7 +98,7 @@ Py::Object range::value( const Py::Tuple &t )
     return c_value(t);
 }
 
-Py::Object range::assign( const Py::Tuple &t ) 
+Py::Object range::assign( const Py::Tuple &t )
 {
     t.verify_length(2);
 
diff --git a/Demo/Python2/range.hxx b/Demo/Python2/range.hxx
index 4a44d10..382e002 100644
--- a/Demo/Python2/range.hxx
+++ b/Demo/Python2/range.hxx
@@ -50,7 +50,7 @@ public:
     long    stop;
     long    step;
 
-    range(long start_, long stop_, long step_ = 1L) 
+    range(long start_, long stop_, long step_ = 1L)
     {
         start = start_;
         stop = stop_;
@@ -87,7 +87,7 @@ public:
 
     range* extend(int k) const
     {
-        return new range(start, stop + k, step);      
+        return new range(start, stop + k, step);
     }
 
     std::string asString() const
@@ -109,7 +109,7 @@ public:
     // define python methods of this object
     Py::Object amethod (const Py::Tuple& args);
     Py::Object value (const Py::Tuple& args);
-    Py::Object assign (const Py::Tuple& args); 
+    Py::Object assign (const Py::Tuple& args);
     Py::Object reference_count (const Py::Tuple& /*args*/)
     {
         return Py::LongLong(this->ob_refcnt);
@@ -144,7 +144,7 @@ public:
         validate();
     }
 
-    explicit RangeSequence(int start, int stop, int step = 1) 
+    explicit RangeSequence(int start, int stop, int step = 1)
     {
         set (new range(start, stop, step), true);
     }
diff --git a/Demo/Python2/rangetest.cxx b/Demo/Python2/rangetest.cxx
index e6cd05d..c7e6b83 100644
--- a/Demo/Python2/rangetest.cxx
+++ b/Demo/Python2/rangetest.cxx
@@ -49,8 +49,8 @@
 extern void debug_check_ref_queue();
 
 
-std::string test_extension_object() 
-{ 
+std::string test_extension_object()
+{
     debug_check_ref_queue();
 
     Py::Tuple a; // just something that isn't an range...
diff --git a/Demo/Python2/simple.cxx b/Demo/Python2/simple.cxx
index f616eab..bcd6a94 100644
--- a/Demo/Python2/simple.cxx
+++ b/Demo/Python2/simple.cxx
@@ -331,7 +331,7 @@ extern "C" EXPORT_SYMBOL PyObject *PyInit_simple()
 
 // symbol required for the debug version
 extern "C" EXPORT_SYMBOL PyObject *PyInit_simple_d()
-{ 
+{
     return PyInit_simple();
 }
 
@@ -350,7 +350,7 @@ extern "C" EXPORT_SYMBOL void initsimple()
 
 // symbol required for the debug version
 extern "C" EXPORT_SYMBOL void initsimple_d()
-{ 
+{
     initsimple();
 }
 #endif
diff --git a/Demo/Python3/example.cxx b/Demo/Python3/example.cxx
index 7ee63c0..58bfbf2 100644
--- a/Demo/Python3/example.cxx
+++ b/Demo/Python3/example.cxx
@@ -346,7 +346,7 @@ void test_float()
     py_float2 = cxx_float2;
     py_float3 = cxx_float3;
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator ==", cxx_float2 == cxx_float3, py_float2  == py_float3 );
     test_assert( "float operator ==", cxx_float2 == cxx_float3, cxx_float2 == py_float3 );
     test_assert( "float operator ==", cxx_float2 == cxx_float3, py_float2  == cxx_float3 );
@@ -355,7 +355,7 @@ void test_float()
     test_assert( "float operator ==", cxx_float1 == cxx_float3, cxx_float1 == py_float3 );
     test_assert( "float operator ==", cxx_float1 == cxx_float3, py_float1  == cxx_float3 );
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator !=", cxx_float1 != cxx_float2, py_float1  != py_float2 );
     test_assert( "float operator !=", cxx_float1 != cxx_float2, cxx_float1 != py_float2 );
     test_assert( "float operator !=", cxx_float1 != cxx_float2, py_float1  != cxx_float2 );
@@ -364,7 +364,7 @@ void test_float()
     test_assert( "float operator !=", cxx_float2 != cxx_float3, cxx_float2 != py_float3 );
     test_assert( "float operator !=", cxx_float2 != cxx_float3, py_float2  != cxx_float3 );
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator < ", cxx_float1 <  cxx_float2, py_float1  <  py_float2 );
     test_assert( "float operator < ", cxx_float1 <  cxx_float2, cxx_float1 <  py_float2 );
     test_assert( "float operator < ", cxx_float1 <  cxx_float2, py_float1  <  cxx_float2 );
@@ -373,7 +373,7 @@ void test_float()
     test_assert( "float operator < ", cxx_float2 <  cxx_float1, cxx_float2 <  py_float1 );
     test_assert( "float operator < ", cxx_float2 <  cxx_float1, py_float2  <  cxx_float1 );
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator > ", cxx_float2 >  cxx_float1, py_float2  >  py_float1 );
     test_assert( "float operator > ", cxx_float2 >  cxx_float1, cxx_float2 >  py_float1 );
     test_assert( "float operator > ", cxx_float2 >  cxx_float1, py_float2  >  cxx_float1 );
@@ -382,7 +382,7 @@ void test_float()
     test_assert( "float operator > ", cxx_float1 >  cxx_float2, cxx_float1 >  py_float2 );
     test_assert( "float operator > ", cxx_float1 >  cxx_float2, py_float1  >  cxx_float2 );
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator <=", cxx_float1 <= cxx_float2, py_float1  <= py_float2 );
     test_assert( "float operator <=", cxx_float1 <= cxx_float2, cxx_float2 <= py_float2 );
     test_assert( "float operator <=", cxx_float1 <= cxx_float2, py_float1  <= cxx_float2 );
@@ -395,7 +395,7 @@ void test_float()
     test_assert( "float operator <=", cxx_float2 <= cxx_float1, cxx_float2 <= py_float1 );
     test_assert( "float operator <=", cxx_float2 <= cxx_float1, py_float2  <= cxx_float1 );
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator >=", cxx_float2 >= cxx_float1, py_float2  >= py_float1 );
     test_assert( "float operator >=", cxx_float2 >= cxx_float1, cxx_float2 >= py_float1 );
     test_assert( "float operator >=", cxx_float2 >= cxx_float1, py_float2  >= cxx_float1 );
@@ -408,7 +408,7 @@ void test_float()
     test_assert( "float operator >=", cxx_float1 >= cxx_float2, cxx_float1 >= py_float2 );
     test_assert( "float operator >=", cxx_float1 >= cxx_float2, py_float1  >= cxx_float2 );
 
-    //------------------------------------------------------------   
+    //------------------------------------------------------------
     test_assert( "float operator float", cxx_float2, float( py_float2 ) );
 }
 
@@ -670,7 +670,7 @@ void debug_check_ref_queue()
         p_slow = p_slow->_ob_next;
         p_fast = p_slow->_ob_next->_ob_next;
 
-        assert( p_slow != p_fast );    
+        assert( p_slow != p_fast );
     }
     while( p_slow != list_element.ptr() );
 
@@ -690,6 +690,7 @@ public:
         add_varargs_method( "sum", &example_module::ex_sum, "sum( arglist ) = sum of arguments" );
         add_varargs_method( "test", &example_module::ex_test, "test( arglist ) runs a test suite" );
         add_varargs_method( "range", &example_module::new_r, "range( start, stop, step )" );
+        add_varargs_method( "return_arg", &example_module::ex_return_arg, "return_arg( arg )" );
         add_keyword_method( "kw", &example_module::ex_keyword, "kw()" );
 
         initialize( "documentation for the example module" );
@@ -720,9 +721,9 @@ private:
         return Py::Long(0);
     }
 
-    Py::Object new_r (const Py::Tuple &rargs)
+    Py::Object new_r( const Py::Tuple &rargs )
     {
-        if (rargs.length() < 2 || rargs.length() > 3)
+        if( rargs.length() < 2 || rargs.length() > 3 )
         {
             throw Py::RuntimeError("Incorrect # of args to range(start,stop [,step]).");
         }
@@ -775,7 +776,12 @@ private:
         }
     }
 
-    Py::Object ex_sum (const Py::Tuple &a)
+    Py::Object ex_return_arg( const Py::Tuple &a )
+    {
+        return a[0];
+    }
+
+    Py::Object ex_sum( const Py::Tuple &a )
     {
         // this is just to test the function verify_length:
         try
@@ -792,7 +798,7 @@ private:
 
         Py::Float f(0.0);
         for( Py::Sequence::size_type i = 0; i < a.length(); i++ )
-        {    
+        {
             Py::Float g (a[i]);
             f = f + g;
         }
@@ -800,6 +806,23 @@ private:
         return f;
     }
 
+    void test_apply()
+    {
+        Py::Module m("example");
+        Py::Callable fn = m.getAttr("return_arg");
+        Py::String s("test_apply string");
+
+        int start_ref = s.reference_count();
+
+        for( int i=0; i<10; ++i )
+        {
+            Py::String result = fn.apply( Py::TupleN( s ) );
+        }
+
+        int end_ref = s.reference_count();
+        test_assert( "apply ref check", start_ref, end_ref );
+    }
+
     Py::Object ex_test( const Py::Tuple &/*args*/ )
     {
         debug_check_ref_queue();
@@ -861,6 +884,10 @@ private:
             std::cout << "Start: test_extension_object" << std::endl;
             test_extension_object();
             debug_check_ref_queue();
+
+            std::cout << "Start: test_apply" << std::endl;
+            test_apply();
+            debug_check_ref_queue();
         }
         catch( TestError &e )
         {
@@ -869,8 +896,9 @@ private:
 
         Py::Module m("sys");
         Py::Object s = m.getAttr("stdout");
-        Py::Object nun;
-        nun = PyObject_CallMethod(s.ptr(), "write", "s", "Module test ok.\n");
+        Py::Object fd  = s.callMemberFunction( "fileno" );
+        test_assert( "stdout fileno() is 1", fd, Py::Long( 1 ) );
+        Py::Object num = s.callMemberFunction( "write", Py::TupleN( Py::String("PASS: Module test ok.\n") ) );
         return Py::None();
     }
 };
@@ -894,6 +922,6 @@ extern "C" EXPORT_SYMBOL PyObject *PyInit_example()
 
 // symbol required for the debug version
 extern "C" EXPORT_SYMBOL PyObject *PyInit_example_d()
-{ 
+{
     return PyInit_example();
 }
diff --git a/Demo/Python3/pycxx_iter.hxx b/Demo/Python3/pycxx_iter.hxx
index 0f8cc16..0b6994f 100644
--- a/Demo/Python3/pycxx_iter.hxx
+++ b/Demo/Python3/pycxx_iter.hxx
@@ -3,7 +3,7 @@
 #include <sstream>
 #include <string>
 
-class IterT : public Py::PythonExtension<IterT> 
+class IterT : public Py::PythonExtension<IterT>
 {
     int from, count, last;
     int fwd_iter;
@@ -58,7 +58,7 @@ public:
                     fwd_iter=2;
                 }
             else if( count <= last )
-                ct= count++; 
+                ct= count++;
             else
                 return NULL;    // signal StopIteration
         }
diff --git a/Demo/Python3/range.cxx b/Demo/Python3/range.cxx
index 681ca99..9831ddc 100644
--- a/Demo/Python3/range.cxx
+++ b/Demo/Python3/range.cxx
@@ -128,7 +128,7 @@ Py_ssize_t range::sequence_length()
     return static_cast<int>( length() );
 }
 
-Py::Object range::sequence_item( Py_ssize_t i ) 
+Py::Object range::sequence_item( Py_ssize_t i )
 {
     return Py::Long( item( static_cast<int>( i ) ) );
 }
@@ -157,7 +157,7 @@ Py::Object range::getattr( const char *name )
 }
 
 // "regular" methods...
-Py::Object range::amethod( const Py::Tuple &t ) 
+Py::Object range::amethod( const Py::Tuple &t )
 {
     t.verify_length( 1 );
     Py::List result;
@@ -172,7 +172,7 @@ Py::Object range::value( const Py::Tuple &t )
     return c_value( t );
 }
 
-Py::Object range::assign( const Py::Tuple &t ) 
+Py::Object range::assign( const Py::Tuple &t )
 {
     t.verify_length( 2 );
 
diff --git a/Demo/Python3/range.hxx b/Demo/Python3/range.hxx
index 49a53c6..5f4b143 100644
--- a/Demo/Python3/range.hxx
+++ b/Demo/Python3/range.hxx
@@ -88,7 +88,7 @@ public:
         validate();
     }
 
-    explicit RangeSequence(long start, long stop, long step = 1) 
+    explicit RangeSequence(long start, long stop, long step = 1)
     {
         set (new range(start, stop, step), true);
     }
diff --git a/Demo/Python3/rangetest.cxx b/Demo/Python3/rangetest.cxx
index ae5d923..5dad8fa 100644
--- a/Demo/Python3/rangetest.cxx
+++ b/Demo/Python3/rangetest.cxx
@@ -47,7 +47,7 @@
 
 // This test also illustrates using the Py namespace explicitly
 
-void test_extension_object() 
+void test_extension_object()
 {
     Py::List a; // just something that is not a range...
 
@@ -67,7 +67,7 @@ void test_extension_object()
     Py::List answer( w.apply( args ) );
 
     test_assert( "extension object amethod 1 q1", answer[0], r2 );
-    test_assert( "extension object amethod 1q2", answer[1], args[0] );
+    test_assert( "extension object amethod 1 q2", answer[1], args[0] );
     }
 
     {
diff --git a/Demo/Python3/simple.cxx b/Demo/Python3/simple.cxx
index b947151..eb48902 100644
--- a/Demo/Python3/simple.cxx
+++ b/Demo/Python3/simple.cxx
@@ -16,7 +16,7 @@
 #include "CXX/Extensions.hxx"
 
 #include <assert.h>
-
+#include <cstring>
 
 class new_style_class: public Py::PythonClass< new_style_class >
 {
@@ -55,6 +55,7 @@ public:
         behaviors().doc( "documentation for new_style_class class" );
         behaviors().supportGetattro();
         behaviors().supportSetattro();
+        behaviors().supportNumberType( Py::PythonType::support_number_add, Py::PythonType::support_number_inplace_add );
 
         PYCXX_ADD_NOARGS_METHOD( func_noargs, new_style_class_func_noargs, "docs for func_noargs" );
         PYCXX_ADD_VARARGS_METHOD( func_varargs, new_style_class_func_varargs, "docs for func_varargs" );
@@ -70,6 +71,21 @@ public:
         behaviors().readyType();
     }
 
+    Py::Object number_add( const Py::Object &other )
+    {
+        std::cout << "new_style_class.number_add called" << std::endl;
+        Py::Long num_to_add( other );
+        return Py::Long( 5 + num_to_add );
+    }
+
+    Py::Object number_inplace_add( const Py::Object &other )
+    {
+        std::cout << "new_style_class.number_inplace_add called..." << std::endl;
+        Py::Long num_to_add( other );
+        std::cout << "... with " << num_to_add << std::endl;
+        return self();
+    }
+
     Py::Object reduce_func( void )
     {
         Py::TupleN ctor_args( m_value );
@@ -248,7 +264,7 @@ public:
         add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()");
         add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()");
         add_keyword_method("derived_class_test", &simple_module::derived_class_test, "documentation for derived_class_test()");
- 
+
         // after initialize the moduleDictionary will exist
         initialize( "documentation for the simple module" );
 
@@ -348,9 +364,9 @@ private:
         }
         catch( SimpleError &e )
         {
-            Py::String value = Py::value( e );
+            Py::Object value = e.errorValue();
             e.clear();
-            std::cout << "PASS caught SimpleError( \"" << value << "\"" << std::endl;
+            std::cout << "PASS caught SimpleError( \"" << value.repr() << "\"" << std::endl;
 
             return Py::String("Error");
         }
@@ -404,6 +420,6 @@ extern "C" EXPORT_SYMBOL PyObject *PyInit_simple()
 
 // symbol required for the debug version
 extern "C" EXPORT_SYMBOL PyObject *PyInit_simple_d()
-{ 
+{
     return PyInit_simple();
 }
diff --git a/Demo/Python3/simple2.cxx b/Demo/Python3/simple2.cxx
index 3f1cda4..c87d15c 100644
--- a/Demo/Python3/simple2.cxx
+++ b/Demo/Python3/simple2.cxx
@@ -78,7 +78,7 @@ private:
         m_string_to_enum[string] = value;
         m_enum_to_string[value] = string;
     }
- 
+
     std::string             m_type_name;
     std::map<std::string,T> m_string_to_enum;
     std::map<T,std::string> m_enum_to_string;
@@ -181,7 +181,7 @@ public:
             return Py::asObject( new pysvn_enum_value<T>( value ) );
         }
 
-        return this->getattr_methods( _name );    
+        return this->getattr_methods( _name );
     }
 
     static void init_type(void);
@@ -224,7 +224,7 @@ Py::List memberList( T value )
         members.append( Py::String( (*it).first ) );
         ++it;
     }
-    
+
     return members;
 }
 
@@ -238,7 +238,7 @@ typedef enum {
 
 template <> EnumString< xxx_t >::EnumString()
 : m_type_name( "xxx" )
-{ 
+{
     add( xxx_first, "first" );
     add( xxx_second, "second" );
     add( xxx_third, "third" );
@@ -362,6 +362,6 @@ extern "C" PyObject *PyInit_simple2()
 
 // symbol required for the debug version
 extern "C" PyObject *PyInit_simple2_d()
-{ 
+{
     return PyInit_simple2();
 }
diff --git a/Demo/Python3/test_assert.hxx b/Demo/Python3/test_assert.hxx
index b62ce6a..0944544 100644
--- a/Demo/Python3/test_assert.hxx
+++ b/Demo/Python3/test_assert.hxx
@@ -15,7 +15,7 @@
 // DAMAGE.
 //
 //  test_assert.hxx
-//  
+//
 class TestError
 {
 public:
diff --git a/Doc/Python3/PyCXX.html b/Doc/Python3/PyCXX.html
index e7e4de2..17df629 100644
--- a/Doc/Python3/PyCXX.html
+++ b/Doc/Python3/PyCXX.html
@@ -2413,10 +2413,38 @@ void supportStr( void );
 void supportHash( void );
 void supportCall( void );
 
-void supportSequenceType( bool support_assignment=true, bool support_inplace=false, bool support_contains=false );
-void supportMappingType( bool support_assignment=true );
-void supportNumberType( void );
-void supportBufferType( void );</pre>
+void supportSequenceType( int methods_to_support=
+                        support_sequence_length |
+                        support_sequence_repeat |
+                        support_sequence_item |
+                        support_sequence_slice |
+                        support_sequence_concat );
+void supportMappingType( int methods_to_support=
+                        support_mapping_length |
+                        support_mapping_subscript );
+void supportNumberType( int methods_to_support=
+                support_number_add |
+                support_number_subtract |
+                support_number_multiply |
+                support_number_remainder |
+                support_number_divmod |
+                support_number_power |
+                support_number_negative |
+                support_number_positive |
+                support_number_absolute |
+                support_number_invert |
+                support_number_lshift |
+                support_number_rshift |
+                support_number_and |
+                support_number_xor |
+                support_number_or |
+                support_number_int |
+                support_number_float,
+            int inplace_methods_to_support=0
+             );
+void supportBufferType(  int methods_to_support=
+                    support_buffer_getbuffer |
+                    support_buffer_releasebuffer );</pre>
 
 <p>Then call add_varargs_method or add_keyword_method to add any methods desired to the
 object.</p>
diff --git a/PyCXX-Release-Notes.txt b/PyCXX-Release-Notes.txt
deleted file mode 100644
index db1653f..0000000
--- a/PyCXX-Release-Notes.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Version: 7.1.3 (1-Jul-2019)
-
-Fix for https://sourceforge.net/p/cxx/bugs/43/
-memory leak caused by wrong ref count on python3 Py::String objects.
-
-Remove support for supportPrint() etc as the tp_print field is
-being removed from python either in 3.8 or 3.9.
diff --git a/README.html b/README.html
index 92c84c7..5554d3a 100644
--- a/README.html
+++ b/README.html
@@ -31,21 +31,21 @@ p.param {background-color: #eeeeee; border-top: lightskyblue solid 4}
 
 <h3>Windows Installation and Demo</h3>
 <ol>
-    <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz">
-    http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz</a></li>
+    <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.1.7.tar.gz">
+    http://prdownloads.sourceforge.net/cxx/pycxx-7.1.7.tar.gz</a></li>
     <li>Expand the archive into a directory of your choosing C:\ for example.</li>
 
     <li>Install the PyCXX files:
         <ol>
-        <li><pre>C:> cd \pycxx-7.1.2</pre></li>
-        <li><pre>C:\pycxx-7.1.2> python setup.py install</pre></li>
+        <li><pre>C:> cd \pycxx-7.1.7</pre></li>
+        <li><pre>C:\pycxx-7.1.7> python setup.py install</pre></li>
         </ol>
     </li>
     <li>Build and run the demo extensions:
         <ol>
-        <li><pre>C:> cd \pycxx-7.1.2</pre></li>
-        <li><pre>C:\pycxx-7.1.2> python setup_makefile.py win32 win32.mak </pre></li>
-        <li><pre>C:\pycxx-7.1.2> nmake -f win32.mak clean test</pre></li>
+        <li><pre>C:> cd \pycxx-7.1.7</pre></li>
+        <li><pre>C:\pycxx-7.1.7> python setup_makefile.py win32 win32.mak </pre></li>
+        <li><pre>C:\pycxx-7.1.7> nmake -f win32.mak clean test</pre></li>
         </ol>
     </li>
 </ol>
@@ -54,18 +54,18 @@ p.param {background-color: #eeeeee; border-top: lightskyblue solid 4}
 <h3>Unix Installation and Demo</h3>
 
 <ol>
-    <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz">
-    http://prdownloads.sourceforge.net/cxx/pycxx-7.1.2.tar.gz</a>
+    <li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx-7.1.7.tar.gz">
+    http://prdownloads.sourceforge.net/cxx/pycxx-7.1.7.tar.gz</a>
     <li>Login as root. root access is typically needed on Unix systems to install the PyCXX files into the Python directories.
     <li>Expand the archive into a directory of your choosing ~\ for example.
     <li>Install the PyCXX files:
         <ol>
-        <li><pre># cd ~/pycxx-7.1.2</pre>
+        <li><pre># cd ~/pycxx-7.1.7</pre>
         <li><pre># python setup.py install</pre>
         </ol>
     <li>Build and run the demo extensions:
         <ol>
-        <li><pre># cd ~/pycxx-7.1.2</pre></li>
+        <li><pre># cd ~/pycxx-7.1.7</pre></li>
         <li><pre># python setup_makefile.py linux linux.mak</pre></li>
         <li><pre># make -f linux.mak clean test</pre></li>
         </ol>
@@ -74,6 +74,39 @@ p.param {background-color: #eeeeee; border-top: lightskyblue solid 4}
 
 <h2>Revision History</h2>
 
+<h3>Version: 7.1.7 (13-Feb-2022)</h3>
+
+<p>This Version 7.1.6 with README updates</p>
+
+<h3>Version: 7.1.6 (14-Feb-2022)</h3>
+
+<p>Add support for building against python 3.11 alpha 4.</p>
+
+<h3>Version: 7.1.5 (21-Feb-2021)</h3>
+
+<p>Replace use of deprecated PyUnicode APIs with the supported version.</p>
+
+<p>The class Py::String functions that used deprecated PyUnicode APIs
+that have no replacements are not available for python 3.9 and later:</p>
+
+<pre>
+    const Py_UNICODE *unicode_data() const;
+    unicodestring as_unicodestring() const;
+</pre>
+
+<p>Replace build-all.sh and build-all.cmd with build-all.py that can handle the build matrix.</p>
+<p>Add limited API builds for all possible combinations.</p>
+<p>Note: Python 3.9 has a bug that prevents use of the limited API until this bug is fix and shipped:
+<a href="https://bugs.python.org/issue43155">BPO 43155</a> for details. 
+The workaround is to set Py_LIMITED_API to use python 3.8.</p>
+
+<h3>Version: 7.1.4 (31-May-2020)</h3>
+
+<p>Add support for more number methods, like matrix and the inplace versions.</p>
+<p>Use IsInstance checking so that derived classes of builtin types can be used.</p>
+<p>Update Docs with recent changes.</p>
+<p>Add support for python 3.9 beta 1 changes.</p>
+
 <h3>Version: 7.1.3 (8-Jul-2019)</h3>
 
 <p>Fix for <a href="https://sourceforge.net/p/cxx/bugs/43/">https://sourceforge.net/p/cxx/bugs/43/</a>
diff --git a/README.txt b/README.txt
index db1653f..1f4d858 100644
--- a/README.txt
+++ b/README.txt
@@ -1,7 +1,5 @@
-Version: 7.1.3 (1-Jul-2019)
+Version: 7.1.7 (13-Feb-2022)
 
-Fix for https://sourceforge.net/p/cxx/bugs/43/
-memory leak caused by wrong ref count on python3 Py::String objects.
+Add support for building against python 3.11 alpha 4.
 
-Remove support for supportPrint() etc as the tp_print field is
-being removed from python either in 3.8 or 3.9.
+This Version 7.1.6 with README updates
diff --git a/Src/IndirectPythonInterface.cxx b/Src/IndirectPythonInterface.cxx
index efa7755..7227f42 100644
--- a/Src/IndirectPythonInterface.cxx
+++ b/Src/IndirectPythonInterface.cxx
@@ -39,33 +39,38 @@
 
 namespace Py
 {
-bool _CFunction_Check( PyObject *op )   { return op->ob_type == _CFunction_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(); }
+static int _IsInstance( PyObject *op, PyTypeObject *type )
+{
+    return PyObject_IsInstance( op, reinterpret_cast<PyObject *>( type ) );
+}
+
+bool _CFunction_Check( PyObject *op )   { return _IsInstance( op, _CFunction_Type() ) > 0; }
+bool _Complex_Check( PyObject *op )     { return _IsInstance( op, _Complex_Type() ) > 0; }
+bool _Dict_Check( PyObject *op )        { return _IsInstance( op, _Dict_Type() ) > 0; }
+bool _Float_Check( PyObject *op )       { return _IsInstance( op, _Float_Type() ) > 0; }
 #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
-bool _Function_Check( PyObject *op )    { return op->ob_type == _Function_Type(); }
+bool _Function_Check( PyObject *op )    { return _IsInstance( op, _Function_Type() ) > 0; }
 #endif
-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 _Boolean_Check( PyObject *op )     { return _IsInstance( op, _Bool_Type() ) > 0; }
+bool _List_Check( PyObject *op )        { return _IsInstance( op, _List_Type() ) > 0; }
+bool _Long_Check( PyObject *op )        { return _IsInstance( op, _Long_Type() ) > 0; }
 #if PY_MAJOR_VERSION == 2 || !defined( Py_LIMITED_API )
-bool _Method_Check( PyObject *op )      { return op->ob_type == _Method_Type(); }
+bool _Method_Check( PyObject *op )      { return _IsInstance( op, _Method_Type() ) > 0; }
 #endif
-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(); }
+bool _Module_Check( PyObject *op )      { return _IsInstance( op, _Module_Type() ) > 0; }
+bool _Range_Check( PyObject *op )       { return _IsInstance( op, _Range_Type() ) > 0; }
+bool _Slice_Check( PyObject *op )       { return _IsInstance( op, _Slice_Type() ) > 0; }
+bool _TraceBack_Check( PyObject *op )   { return _IsInstance( op, _TraceBack_Type() ) > 0; }
+bool _Tuple_Check( PyObject *op )       { return _IsInstance( op, _Tuple_Type() ) > 0; }
+bool _Type_Check( PyObject *op )        { return _IsInstance( op, _Type_Type() ) > 0; }
+bool _Unicode_Check( PyObject *op )     { return _IsInstance( op, _Unicode_Type() ) > 0; }
 #if PY_MAJOR_VERSION == 2
-bool _String_Check( PyObject *op )      { return op->ob_type == _String_Type(); }
-bool _Int_Check( PyObject *op )         { return op->ob_type == _Int_Type(); }
-bool _CObject_Check( PyObject *op )     { return op->ob_type == _CObject_Type(); }
+bool _String_Check( PyObject *op )      { return _IsInstance( op, _String_Type() ) > 0; }
+bool _Int_Check( PyObject *op )         { return _IsInstance( op, _Int_Type() ) > 0; }
+bool _CObject_Check( PyObject *op )     { return _IsInstance( op, _CObject_Type() ) > 0; }
 #endif
 #if PY_MAJOR_VERSION >= 3
-bool _Bytes_Check( PyObject *op )       { return op->ob_type == _Bytes_Type(); }
+bool _Bytes_Check( PyObject *op )       { return _IsInstance( op, _Bytes_Type() ) > 0; }
 #endif
 
 #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
diff --git a/Src/Python2/cxxextensions.c b/Src/Python2/cxxextensions.c
index edae3be..07845e8 100644
--- a/Src/Python2/cxxextensions.c
+++ b/Src/Python2/cxxextensions.c
@@ -38,7 +38,7 @@
 #include "CXX/WrapPython.h"
 
 #ifdef __cplusplus
-extern "C" 
+extern "C"
 {
 #endif
 
diff --git a/Src/Python2/cxxsupport.cxx b/Src/Python2/cxxsupport.cxx
index 1dfba5a..fa0cfd9 100644
--- a/Src/Python2/cxxsupport.cxx
+++ b/Src/Python2/cxxsupport.cxx
@@ -41,7 +41,7 @@ namespace Py {
 Py_UNICODE unicode_null_string[1] = { 0 };
 
 Type Object::type () const
-{ 
+{
     return Type (PyObject_Type (p), true);
 }
 
@@ -51,7 +51,7 @@ String Object::str () const
 }
 
 String Object::repr () const
-{ 
+{
     return String (PyObject_Repr (p), true);
 }
 
@@ -66,7 +66,7 @@ List Object::dir () const
         }
 
 bool Object::isType (const Type& t) const
-{ 
+{
     return type ().ptr() == t.ptr();
 }
 
@@ -168,7 +168,7 @@ bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterat
 std::ostream& operator<< (std::ostream& os, const Object& ob)
 {
     return (os << static_cast<std::string>(ob.str()));
-}  
+}
 #endif
 
 } // Py
diff --git a/Src/Python3/cxx_extensions.cxx b/Src/Python3/cxx_extensions.cxx
index 3217de5..c91227c 100644
--- a/Src/Python3/cxx_extensions.cxx
+++ b/Src/Python3/cxx_extensions.cxx
@@ -282,6 +282,28 @@ extern "C"
     static PyObject *number_xor_handler( PyObject *, PyObject * );
     static PyObject *number_or_handler( PyObject *, PyObject * );
     static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * );
+    static PyObject *number_floor_divide_handler( PyObject *, PyObject * );
+    static PyObject *number_true_divide_handler( PyObject *, PyObject * );
+    static PyObject *number_index_handler( PyObject * );
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+    static PyObject *number_matrix_multiply_handler( PyObject *, PyObject * );
+#endif
+
+    static PyObject *number_inplace_add_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_subtract_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_multiply_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_remainder_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_power_handler( PyObject *, PyObject *, PyObject * );
+    static PyObject *number_inplace_lshift_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_rshift_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_and_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_xor_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_or_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_floor_divide_handler( PyObject *, PyObject * );
+    static PyObject *number_inplace_true_divide_handler( PyObject *, PyObject * );
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+    static PyObject *number_inplace_matrix_multiply_handler( PyObject *, PyObject * );
+#endif
 
     // Buffer
 #if !defined( Py_LIMITED_API )
@@ -391,14 +413,22 @@ PythonType &PythonType::supportMappingType( int methods_to_support )
     if( methods_to_support&support_number_ ## slot ) { \
         slots[ Py_nb_ ## slot ] = reinterpret_cast<void *>( number_ ## slot ## _handler ); \
     }
+#define FILL_NUMBER_INPLACE_SLOT(slot) \
+    if( inplace_methods_to_support&support_number_ ## slot ) { \
+        slots[ Py_nb_ ## slot ] = reinterpret_cast<void *>( number_ ## slot ## _handler ); \
+    }
 #else
 #define FILL_NUMBER_SLOT(slot) \
     if( methods_to_support&support_number_ ## slot ) { \
         number_table->nb_ ## slot = number_ ## slot ## _handler; \
     }
+#define FILL_NUMBER_INPLACE_SLOT(slot) \
+    if( inplace_methods_to_support&support_number_ ## slot ) { \
+        number_table->nb_ ## slot = number_ ## slot ## _handler; \
+    }
 #endif
 
-PythonType &PythonType::supportNumberType( int methods_to_support )
+PythonType &PythonType::supportNumberType( int methods_to_support, int inplace_methods_to_support )
 {
 #if !defined( Py_LIMITED_API )
     if( number_table )
@@ -427,6 +457,29 @@ PythonType &PythonType::supportNumberType( int methods_to_support )
     FILL_NUMBER_SLOT(or)
     FILL_NUMBER_SLOT(int)
     FILL_NUMBER_SLOT(float)
+    FILL_NUMBER_SLOT(floor_divide)
+    FILL_NUMBER_SLOT(true_divide)
+    FILL_NUMBER_SLOT(index)
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+    FILL_NUMBER_SLOT(matrix_multiply)
+#endif
+
+    FILL_NUMBER_INPLACE_SLOT(inplace_add)
+    FILL_NUMBER_INPLACE_SLOT(inplace_subtract)
+    FILL_NUMBER_INPLACE_SLOT(inplace_multiply)
+    FILL_NUMBER_INPLACE_SLOT(inplace_remainder)
+    FILL_NUMBER_INPLACE_SLOT(inplace_power)
+    FILL_NUMBER_INPLACE_SLOT(inplace_lshift)
+    FILL_NUMBER_INPLACE_SLOT(inplace_rshift)
+    FILL_NUMBER_INPLACE_SLOT(inplace_and)
+    FILL_NUMBER_INPLACE_SLOT(inplace_xor)
+    FILL_NUMBER_INPLACE_SLOT(inplace_or)
+    FILL_NUMBER_INPLACE_SLOT(inplace_floor_divide)
+    FILL_NUMBER_INPLACE_SLOT(inplace_true_divide)
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+    FILL_NUMBER_INPLACE_SLOT(inplace_matrix_multiply)
+#endif
+
     return *this;
 }
 
@@ -1139,226 +1192,89 @@ extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyO
 }
 
 // Number
-extern "C" PyObject *number_negative_handler( PyObject *self )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_negative() );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_positive_handler( PyObject *self )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_positive() );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_absolute_handler( PyObject *self )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_absolute() );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_invert_handler( PyObject *self )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_invert() );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_int_handler( PyObject *self )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_int() );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_float_handler( PyObject *self )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_float() );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_add_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_add( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_subtract_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_subtract( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_multiply_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_multiply( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_remainder_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_remainder( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_divmod_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_divmod( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_lshift_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_lshift( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_rshift_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_rshift( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_and_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_and( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_xor_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_xor( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
-
-extern "C" PyObject *number_or_handler( PyObject *self, PyObject *other )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_or( Object( other ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
+#define NUMBER_UNARY( slot ) \
+extern "C" PyObject *number_ ## slot ## _handler( PyObject *self ) \
+{ \
+    try \
+    { \
+        PythonExtensionBase *p = getPythonExtensionBase( self ); \
+        return new_reference_to( p->number_ ## slot() ); \
+    } \
+    catch( BaseException & ) \
+    { \
+        return NULL; /* indicates error */ \
+    } \
+}
+
+#define NUMBER_BINARY( slot ) \
+extern "C" PyObject *number_ ## slot ## _handler( PyObject *self, PyObject *other ) \
+{ \
+    try \
+    { \
+        PythonExtensionBase *p = getPythonExtensionBase( self ); \
+        return new_reference_to( p->number_ ## slot( Object( other ) ) ); \
+    } \
+    catch( BaseException & ) \
+    { \
+        return NULL; /* indicates error */ \
+    } \
+}
+#define NUMBER_TERNARY( slot ) \
+extern "C" PyObject *number_ ## slot ## _handler( PyObject *self, PyObject *other1, PyObject *other2 ) \
+{ \
+    try \
+    { \
+        PythonExtensionBase *p = getPythonExtensionBase( self ); \
+        return new_reference_to( p->number_ ## slot( Object( other1 ), Object( other2 ) ) ); \
+    } \
+    catch( BaseException & ) \
+    { \
+        return NULL; /* indicates error */ \
+    } \
+}
+
+NUMBER_UNARY( negative )
+NUMBER_UNARY( positive )
+NUMBER_UNARY( absolute )
+NUMBER_UNARY( invert )
+NUMBER_UNARY( int )
+NUMBER_UNARY( float )
+NUMBER_BINARY( add )
+NUMBER_BINARY( subtract )
+NUMBER_BINARY( multiply )
+NUMBER_BINARY( remainder )
+NUMBER_BINARY( divmod )
+NUMBER_BINARY( lshift )
+NUMBER_BINARY( rshift )
+NUMBER_BINARY( and )
+NUMBER_BINARY( xor )
+NUMBER_BINARY( or )
+NUMBER_TERNARY( power )
+NUMBER_BINARY( floor_divide )
+NUMBER_BINARY( true_divide )
+NUMBER_UNARY( index )
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+NUMBER_BINARY( matrix_multiply )
+#endif
+NUMBER_BINARY( inplace_add )
+NUMBER_BINARY( inplace_subtract )
+NUMBER_BINARY( inplace_multiply )
+NUMBER_BINARY( inplace_remainder )
+NUMBER_TERNARY( inplace_power )
+NUMBER_BINARY( inplace_lshift )
+NUMBER_BINARY( inplace_rshift )
+NUMBER_BINARY( inplace_and )
+NUMBER_BINARY( inplace_xor )
+NUMBER_BINARY( inplace_or )
+NUMBER_BINARY( inplace_floor_divide )
+NUMBER_BINARY( inplace_true_divide )
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+NUMBER_BINARY( inplace_matrix_multiply )
+#endif
 
-extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 )
-{
-    try
-    {
-        PythonExtensionBase *p = getPythonExtensionBase( self );
-        return new_reference_to( p->number_power( Object( x1 ), Object( x2 ) ) );
-    }
-    catch( BaseException & )
-    {
-        return NULL;    // indicate error
-    }
-}
+#undef NUMBER_UNARY
+#undef NUMBER_BINARY
+#undef NUMBER_TERNARY
 
 // Buffer
 #ifndef Py_LIMITED_API
@@ -1620,95 +1536,57 @@ int PythonExtensionBase::mapping_ass_subscript( const Object &, const Object & )
     missing_method( mapping_ass_subscript );
 }
 
-Object PythonExtensionBase::number_negative()
-{
-    missing_method( number_negative );
-}
-
-Object PythonExtensionBase::number_positive()
-{
-    missing_method( number_positive );
-}
-
-Object PythonExtensionBase::number_absolute()
-{
-    missing_method( number_absolute );
-}
-
-Object PythonExtensionBase::number_invert()
-{
-    missing_method( number_invert );
-}
-
-Object PythonExtensionBase::number_int()
-{
-    missing_method( number_int );
-}
-
-Object PythonExtensionBase::number_float()
-{
-    missing_method( number_float );
-}
-
-Object PythonExtensionBase::number_long()
-{
-    missing_method( number_long );
-}
-
-Object PythonExtensionBase::number_add( const Object & )
-{
-    missing_method( number_add );
-}
-
-Object PythonExtensionBase::number_subtract( const Object & )
-{
-    missing_method( number_subtract );
-}
-
-Object PythonExtensionBase::number_multiply( const Object & )
-{
-    missing_method( number_multiply );
-}
-
-Object PythonExtensionBase::number_remainder( const Object & )
-{
-    missing_method( number_remainder );
-}
-
-Object PythonExtensionBase::number_divmod( const Object & )
-{
-    missing_method( number_divmod );
-}
-
-Object PythonExtensionBase::number_lshift( const Object & )
-{
-    missing_method( number_lshift );
-}
-
-Object PythonExtensionBase::number_rshift( const Object & )
-{
-    missing_method( number_rshift );
-}
-
-Object PythonExtensionBase::number_and( const Object & )
-{
-    missing_method( number_and );
-}
-
-Object PythonExtensionBase::number_xor( const Object & )
-{
-    missing_method( number_xor );
-}
+// Number
+#define NUMBER_UNARY( slot ) Object PythonExtensionBase::number_ ## slot() \
+    { missing_method( number_ ## slot ); }
+#define NUMBER_BINARY( slot ) Object PythonExtensionBase::number_ ## slot( const Object & ) \
+    { missing_method( number_ ## slot ); }
+#define NUMBER_TERNARY( slot ) Object PythonExtensionBase::number_ ## slot( const Object &, const Object & ) \
+    { missing_method( number_ ## slot ); }
+
+NUMBER_UNARY( negative )
+NUMBER_UNARY( positive )
+NUMBER_UNARY( absolute )
+NUMBER_UNARY( invert )
+NUMBER_UNARY( int )
+NUMBER_UNARY( float )
+NUMBER_BINARY( add )
+NUMBER_BINARY( subtract )
+NUMBER_BINARY( multiply )
+NUMBER_BINARY( remainder )
+NUMBER_BINARY( divmod )
+NUMBER_BINARY( lshift )
+NUMBER_BINARY( rshift )
+NUMBER_BINARY( and )
+NUMBER_BINARY( xor )
+NUMBER_BINARY( or )
+NUMBER_TERNARY( power )
+NUMBER_BINARY( floor_divide )
+NUMBER_BINARY( true_divide )
+NUMBER_UNARY( index )
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+NUMBER_BINARY( matrix_multiply )
+#endif
 
-Object PythonExtensionBase::number_or( const Object & )
-{
-    missing_method( number_or );
-}
+NUMBER_BINARY( inplace_add )
+NUMBER_BINARY( inplace_subtract )
+NUMBER_BINARY( inplace_multiply )
+NUMBER_BINARY( inplace_remainder )
+NUMBER_TERNARY( inplace_power )
+NUMBER_BINARY( inplace_lshift )
+NUMBER_BINARY( inplace_rshift )
+NUMBER_BINARY( inplace_and )
+NUMBER_BINARY( inplace_xor )
+NUMBER_BINARY( inplace_or )
+NUMBER_BINARY( inplace_floor_divide )
+NUMBER_BINARY( inplace_true_divide )
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
+NUMBER_BINARY( inplace_matrix_multiply )
+#endif
 
-Object PythonExtensionBase::number_power( const Object &, const Object & )
-{
-    missing_method( number_power );
-}
+#undef NUMBER_UNARY
+#undef NUMBER_BINARY
+#undef NUMBER_TERNARY
 
 
 // Buffer
diff --git a/Src/Python3/cxxextensions.c b/Src/Python3/cxxextensions.c
index 7feb1e0..3b0f8ef 100644
--- a/Src/Python3/cxxextensions.c
+++ b/Src/Python3/cxxextensions.c
@@ -38,14 +38,14 @@
 #include "CXX/WrapPython.h"
 
 #ifdef __cplusplus
-extern "C" 
+extern "C"
 {
 #endif
 
-PyObject py_object_initializer = 
+PyObject py_object_initializer =
     {
     _PyObject_EXTRA_INIT
-    1, 
+    1,
     NULL    // type must be init'ed by user
     };
 
diff --git a/Src/Python3/cxxsupport.cxx b/Src/Python3/cxxsupport.cxx
index 90ca127..cad2a70 100644
--- a/Src/Python3/cxxsupport.cxx
+++ b/Src/Python3/cxxsupport.cxx
@@ -36,7 +36,7 @@
 //-----------------------------------------------------------------------------
 
 #include "CXX/Objects.hxx"
-namespace Py 
+namespace Py
 {
 #if !defined(Py_LIMITED_API)
 Py_UNICODE unicode_null_string[1] = { 0 };
@@ -44,7 +44,7 @@ Py_UNICODE unicode_null_string[1] = { 0 };
 Py_UCS4 ucs4_null_string[1] = { 0 };
 
 Type Object::type() const
-{ 
+{
     return Type( PyObject_Type( p ), true );
 }
 
@@ -54,7 +54,7 @@ String Object::str() const
 }
 
 String Object::repr() const
-{ 
+{
     return String( PyObject_Repr( p ), true );
 }
 
@@ -217,7 +217,7 @@ bool operator!=( const Mapping::const_iterator &left, const Mapping::const_itera
 std::ostream &operator<<( std::ostream &os, const Object &ob )
 {
     return( os << static_cast<std::string>( ob.str() ) );
-}  
+}
 #endif
 
 } // Py
diff --git a/build-all.cmd b/build-all.cmd
index 6f80496..d10e5fa 100644
--- a/build-all.cmd
+++ b/build-all.cmd
@@ -1,48 +1 @@
-if not "%1%2" == "" goto :build_%1_%2
-
-:build_27_32
-    call build-unlimited-api.cmd 27 win32 9.0
-if not "%1%2" == "" goto :eof
-
-:build_33_32
-    call build-unlimited-api.cmd 33 win32 10.0
-if not "%1%2" == "" goto :eof
-
-:build_34_32
-    call build-unlimited-api.cmd 34 win32 10.0
-    call build-limited-api.cmd 34 win32 10.0 3.4
-if not "%1%2" == "" goto :eof
-
-:build_35_32
-    call build-unlimited-api.cmd 35 win32 14.0
-    call build-limited-api.cmd 35 win32 14.0 3.4
-    call build-limited-api.cmd 35 win32 14.0 3.5
-if not "%1%2" == "" goto :eof
-
-:build_27_64
-    call build-unlimited-api.cmd 27 win64 9.0
-if not "%1%2" == "" goto :eof
-
-:build_35_64
-    call build-unlimited-api.cmd 35 win64 14.0
-    call build-limited-api.cmd 35 win64 14.0 3.4
-    call build-limited-api.cmd 35 win64 14.0 3.5
-if not "%1%2" == "" goto :eof
-
-:build_36_64
-    call build-unlimited-api.cmd 36 win64 14.0
-    call build-limited-api.cmd 36 win64 14.0 3.4
-    call build-limited-api.cmd 36 win64 14.0 3.6
-if not "%1%2" == "" goto :eof
-
-:build_37_64
-    call build-unlimited-api.cmd 37 win64 14.0
-    call build-limited-api.cmd 37 win64 14.0 3.4
-    call build-limited-api.cmd 37 win64 14.0 3.7
-if not "%1%2" == "" goto :eof
-
-:build_38_64
-    call build-unlimited-api.cmd 38 win64 14.0
-    call build-limited-api.cmd 38 win64 14.0 3.4
-    call build-limited-api.cmd 38 win64 14.0 3.7
-if not "%1%2" == "" goto :eof
+py -3 build-all.py
diff --git a/build-all.py b/build-all.py
new file mode 100755
index 0000000..1a42322
--- /dev/null
+++ b/build-all.py
@@ -0,0 +1,110 @@
+#!/usr/bin/python3
+import sys
+import subprocess
+
+first_limited_api_minor = 4
+
+# (major, minor, bits, vc_ver)
+default_versions_to_test = [
+    (2,  7, 32,  '9.0'), (2,  7, 64,  '9.0'),
+    (3,  3, 32, '10.0'),     # no compiler for windows 64 bit
+    (3,  4, 32, '10.0'),     # no compiler for windows 64 bit
+    (3,  5, 32, '14.0'), (3,  5, 64, '14.0'),
+    (3,  6, 32, '14.0'), (3,  6, 64, '14.0'),
+    (3,  7, 32, '14.0'), (3,  7, 64, '14.0'),
+    (3,  8, 32, '14.0'), (3,  8, 64, '14.0'),
+    (3,  9, 32, '14.0'), (3,  9, 64, '14.0'),
+    (3, 10, 32, '14.0'), (3, 10, 64, '14.0'),
+    (3, 11, 32, '14.0'), (3, 11, 64, '14.0'),
+]
+
+def main( argv ):
+    dry_run = False
+    all_versions_to_test = []
+
+    for arg in argv[1:]:
+        if arg == '--dry-run':
+            dry_run = True
+        else:
+            # convert all the args into a list of verions to test
+            # assume py.exe format maj.min or maj.min-bits
+            try:
+                if '-' in arg:
+                    major_minor, bits = arg.split('-')
+
+                else:
+                    major_minor = arg
+                    bits = '64'
+
+                major, minor = major_minor.split('.')
+
+                major = int(major)
+                minor = int(minor)
+                bits = int(bits)
+
+            except ValueError:
+                print( 'Error: Expecting <major>.<minor>[-<bits>] 3.9-64 given %r' % (arg,) )
+                return 1
+
+            # find the vc_ver from the default_versions_to_test
+            vc_ver = None
+            for info in default_versions_to_test:
+                if info[:3] == (major, minor, bits):
+                    vc_ver = info[3]
+
+            if vc_ver is None:
+                print( 'Error: Update default_versions_to_test for %d.%d-%d - vc_ver cannot be determined' %
+                            (major, minor, bits) )
+                return 1
+
+            all_versions_to_test.append( (major, minor, bits, vc_ver) )
+
+    if len(all_versions_to_test) == 0:
+        all_versions_to_test = default_versions_to_test
+
+    #
+    #   Run all the requested builds
+    #
+    is_win = sys.platform.startswith( 'win' )
+    for major, minor, bits, vc_ver in all_versions_to_test:
+        if is_win:
+            fmt = '.\\%s.cmd'
+
+        else:
+            # Only windows needs to build both 32 and 64 bit
+            # for the mac and linux only build once
+            if bits == 32:
+                continue
+
+            fmt = './%s.sh'
+
+        if is_win:
+            cmd = [fmt % ('build-unlimited-api',), '%d.%d' % (major, minor), '%d' % (bits,), vc_ver]
+
+        else:
+            cmd = [fmt % ('build-unlimited-api',), 'python%d.%d' % (major, minor)]
+
+        print( 'Info: %s' % (' '.join(cmd),), flush=True )
+        if not dry_run:
+            subprocess.run( cmd )
+
+        if major == 2:
+            continue
+
+        for api_minor in range( first_limited_api_minor, minor+1 ):
+            if is_win:
+                cmd = [fmt % ('build-limited-api',), '%d.%d' % (major, minor), '%d' % (bits,), vc_ver]
+
+            else:
+                cmd = [fmt % ('build-limited-api',), 'python%d.%d' % (major, minor)]
+
+            # add the API version to use
+            cmd.append( '%d.%d' % (major, api_minor) )
+            print( 'Info: %s' % (' '.join(cmd),), flush=True )
+            if not dry_run:
+                subprocess.run( cmd )
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit( main( sys.argv ) )
diff --git a/build-all.sh b/build-all.sh
index a45675b..a98712d 100755
--- a/build-all.sh
+++ b/build-all.sh
@@ -1,31 +1,3 @@
 #!/bin/bash
-set -x
 set -e
-set -o pipefail
-
-for PYTHON in \
-    python2.6 \
-    python2.7 \
-    python3.3 \
-    python3.4 \
-    python3.5 \
-    python3.6 \
-    python3.7 \
-    python3.8 \
-    python3.9 \
-    ;
-do
-    if which $PYTHON >/dev/null
-    then
-        echo "Info: Found ${PYTHON}"
-        ./build-unlimited-api.sh ${PYTHON}
-
-        case "${PYTHON}" in
-        python3.3)
-            ;;
-        python3.*)
-            ./build-limited-api.sh ${PYTHON} ${PYTHON#python}
-            ;;
-        esac
-    fi
-done
+./build-all.py "$@"
diff --git a/build-limited-api.cmd b/build-limited-api.cmd
index f2cf8ca..f749e14 100644
--- a/build-limited-api.cmd
+++ b/build-limited-api.cmd
@@ -1,10 +1,11 @@
 setlocal
-rem Mm e.g. 24 36 etc
+rem M.m e.g. 2.7 3.6 etc
 set PYTHON_VER=%1
-rem win32 or win64
+rem 32 or 64
 set PYTHON_ARCH=%2
 rem 10.0, 14.0
 set VC_VER=%3
+rem 3.5 etc
 set API=%4
 
 echo ------------------------------------------------------
@@ -28,11 +29,11 @@ if %PYTHON_ARCH% == win64 (
 )
 
 if exist c:\python%PYTHON_VER%.%PYTHON_ARCH%\python.exe (
-    c:\python%PYTHON_VER%.%PYTHON_ARCH%\python setup_makefile.py %PYTHON_ARCH% tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak --limited-api=%API%
+    py -%PYTHON_VER%-%PYTHON_ARCH% setup_makefile.py win%PYTHON_ARCH% tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak --limited-api=%API%
     if errorlevel 1 exit /b 1
-    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak clean all 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.log
+    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak clean all 2>&1 | py -3 build_tee tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.log
     if not exist obj\pycxx_iter.pyd exit /b 1
-    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak test 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-test.log
+    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-build.mak test 2>&1 | py -3 build_tee -a tmp-%PYTHON_ARCH%-python%PYTHON_VER%-limited-%API%-test.log
     echo All done
 )
 endlocal
diff --git a/build-limited-api.sh b/build-limited-api.sh
index 3c65273..b592180 100755
--- a/build-limited-api.sh
+++ b/build-limited-api.sh
@@ -21,6 +21,6 @@ esac
 
 PYTHON_BASE=$(basename ${PYTHON})
 
-${PYTHON} setup_makefile.py ${OS} tmp-${PYTHON_BASE}-limited-api.mak --limited-api=${API}
-make -f tmp-${PYTHON_BASE}-limited-api.mak clean 2>&1 | tee tmp-${PYTHON_BASE}-limited-api.log
-make -f tmp-${PYTHON_BASE}-limited-api.mak test 2>&1 | tee -a tmp-${PYTHON_BASE}-limited-api.log
+${PYTHON} setup_makefile.py ${OS} tmp-${PYTHON_BASE}-limited-api-${API}.mak --limited-api=${API}
+make -f tmp-${PYTHON_BASE}-limited-api-${API}.mak clean 2>&1 | tee tmp-${PYTHON_BASE}-limited-api-${API}.log
+make -f tmp-${PYTHON_BASE}-limited-api-${API}.mak test 2>&1 | tee -a tmp-${PYTHON_BASE}-limited-api-${API}.log
diff --git a/build-unlimited-api.cmd b/build-unlimited-api.cmd
index 44848a6..16a97b2 100644
--- a/build-unlimited-api.cmd
+++ b/build-unlimited-api.cmd
@@ -38,8 +38,8 @@ if %PYTHON_ARCH% == win64 (
 if exist c:\python%PYTHON_VER%.%PYTHON_ARCH%\python.exe (
     c:\python%PYTHON_VER%.%PYTHON_ARCH%\python setup_makefile.py %PYTHON_ARCH% tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak
     if errorlevel 1 exit /b 1
-    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak clean all 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.log
+    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak clean all 2>&1 | py -3 build_tee tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.log
     if not exist obj\pycxx_iter.pyd exit /b 1
-    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak test 2>&1 | c:\UnxUtils\usr\local\wbin\tee.exe tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-test.log
+    nmake -f tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-build.mak test 2>&1 | py -3 build_tee -a tmp-%PYTHON_ARCH%-python%PYTHON_VER%-unlimited-test.log
 )
 endlocal
diff --git a/build_tee.py b/build_tee.py
new file mode 100644
index 0000000..6b64b44
--- /dev/null
+++ b/build_tee.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+import sys
+import re
+
+def main( argv ):
+    all_copies = []
+    i_args = iter( argv )
+    next( i_args )
+
+    mode = 'w'
+
+    for filename in i_args:
+        if filename == '-a':
+            mode = 'a'
+        else:
+            all_copies.append( open( filename, 'w' ) )
+
+    colour = re.compile( r'\033\[[\d;]*m' )
+
+    for line in sys.stdin:
+        # allow colours to be shown seen
+        sys.stdout.write( line )
+
+        # remove colouring from log files.
+        line = colour.sub( '', line )
+
+        for copy in all_copies:
+            copy.write( line )
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit( main( sys.argv ) )
diff --git a/debian/changelog b/debian/changelog
index ea3140a..464c930 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-pycxx (7.1.3-1) UNRELEASED; urgency=medium
+pycxx (7.1.7-1) UNRELEASED; urgency=medium
 
   [ Debian Janitor ]
   * Trim trailing whitespace.
@@ -10,7 +10,10 @@ pycxx (7.1.3-1) UNRELEASED; urgency=medium
   * d/control: Update Vcs-* fields with new Debian Python Team Salsa
     layout.
 
- -- Debian Janitor <janitor@jelmer.uk>  Fri, 24 Apr 2020 13:16:48 +0000
+  [ Debian Janitor ]
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Fri, 20 May 2022 16:03:44 -0000
 
 pycxx (7.1.3-0.1) unstable; urgency=medium
 
diff --git a/debian/patches/fix-32-bit-adt.patch b/debian/patches/fix-32-bit-adt.patch
index 588cc81..1a17cf6 100644
--- a/debian/patches/fix-32-bit-adt.patch
+++ b/debian/patches/fix-32-bit-adt.patch
@@ -3,9 +3,11 @@ Bug-Debian: https://bugs.debian.org/888414
 Author: Graham Inggs <ginggs@debian.org>
 Last-Update: 2018-01-26
 
---- a/Demo/Python3/test_assert.hxx
-+++ b/Demo/Python3/test_assert.hxx
-@@ -54,6 +54,11 @@
+Index: pycxx/Demo/Python3/test_assert.hxx
+===================================================================
+--- pycxx.orig/Demo/Python3/test_assert.hxx
++++ pycxx/Demo/Python3/test_assert.hxx
+@@ -54,6 +54,11 @@ static void test_assert( const char *des
      test_assert_scaler( description, "int", benchmark, value );
  }
  
diff --git a/how_to_release_pycxx.txt b/how_to_release_pycxx.txt
index 8db345e..fe51fce 100644
--- a/how_to_release_pycxx.txt
+++ b/how_to_release_pycxx.txt
@@ -2,7 +2,7 @@ How to release PyCXX
 --------------------
 
 0.  Update CXX/Version.hxx with the releases version number
-    Update README.html, PyCXX-Release-Notes.txt with change log info
+    Update README.html, README.txt with change log info
 1.  Tag the source using tag_pycxx.py (depends on pysvn).
 2.  Create the source kit using make_src_kit.py
 3.  Add new File release on sourceforge.
@@ -11,7 +11,7 @@ How to release PyCXX
     3. Open CXX folder
     4. Click "Add Folder"
     5. Name the Folder PyCXX V<maj>.<min>.<patch> e.g. PyCXX V6.1.1
-    7. Upload the source kit and its PyCXX-Release-Notes-readme.txt (as README.txt)
+    7. Upload the source kit and its README.txt
     9. Click on the source kit (i) icon and choose Select All platforms. Do not select all for README.txt.
 4.  Add news about release
     1. Click News
diff --git a/setup_makefile.py b/setup_makefile.py
index 85d1944..99ee103 100644
--- a/setup_makefile.py
+++ b/setup_makefile.py
@@ -18,7 +18,7 @@ class Setup:
     def __init__( self, argv ):
         args = argv[1:]
         if len(args) < 2:
-            raise ValueError( 'Usage: setup.py win32|win64|macosx|linux> <makefile>' )
+            raise ValueError( 'Usage: setup_makefile.py win32|win64|macosx|linux> <makefile>' )
 
         self.opt_debug = False
         self.opt_pycxx_debug = False
diff --git a/tag_pycxx.py b/tag_pycxx.py
index 1894b18..23cf36e 100644
--- a/tag_pycxx.py
+++ b/tag_pycxx.py
@@ -2,6 +2,25 @@ import pysvn
 import sys
 import os
 
+def check_version( version ):
+    vars = {}
+    with open('CXX/Version.hxx') as f:
+        for line in f:
+            words = line.split()
+
+            if( len(words) >= 3
+            and words[0] == '#define'
+            and words[1].startswith('PYCXX_VERSION_') ):
+                vars[ words[1] ] = words[2]
+
+    defined_version = '%(PYCXX_VERSION_MAJOR)s.%(PYCXX_VERSION_MINOR)s.%(PYCXX_VERSION_PATCH)s' % vars
+    print( 'Info: %s defined in Version.hxx' % (defined_version,) )
+    if defined_version == version:
+        return True
+
+    print( 'Error: %s does not match defined version' % (version,) )
+    return False
+
 def make_tag( from_url, tag_base_url, version ):
     client = pysvn.Client()
     client.callback_get_log_message = lambda : (True, 'Tag version '+version)
@@ -18,19 +37,19 @@ def make_tag( from_url, tag_base_url, version ):
         tag_files = client.ls( tag_base_url, recurse=False )
         print( 'Info: Found', tag_base_url )
     except pysvn.ClientError as e:
-        print( 'Error: Tag base does not exist',tag_base_url )
+        print( 'Error: Tag base does not exist', tag_base_url )
         return
 
     cur_versions = [os.path.basename(f['name']) for f in tag_files]
 
     if version in cur_versions:
-        print( 'Error: Already tagged',version )
+        print( 'Error: Already tagged', version )
         return
 
 
     try:
         to_url = tag_base_url + '/' + version
-        print( 'Info: Copy',repr(from_url), repr(to_url) )
+        print( 'Info: Copy', repr(from_url), repr(to_url) )
         client.copy( from_url, to_url )
         print( 'Info: Copy complete' )
     except pysvn.ClientError as e:
@@ -38,36 +57,40 @@ def make_tag( from_url, tag_base_url, version ):
         return
 
 def callback_getLogin( realm, username, may_save ):
-    print( 'May save:',may_save )
-    print( 'Realm:',realm )
+    print( 'May save:', may_save )
+    print( 'Realm:', realm )
     if username:
-        print( 'Username:',username )
+        print( 'Username:', username )
     else:
-        sys.stdout.write( 'Username: ' )
+        print( 'Username: ', end='', flush=True )
         username = sys.stdin.readline().strip()
         if len(username) == 0:
             return 0, '', '', False
 
-    sys.stdout.write( 'Password: ' )
+    print( 'Password: ', end='', flush=True )
     password = sys.stdin.readline().strip()
 
     save_password = 'x'
     while save_password.lower() not in ['y','ye','yes','n', 'no','']:
-        sys.stdout.write( 'Save password? [y/n] ' )
+        print( 'Save password? [y/n] ', end='', flush=True )
         save_password = sys.stdin.readline().strip()
 
     return 1, username, password, save_password in ['y','ye','yes']
 
-def main():
-    if len(sys.argv) != 2:
-        print( 'Usage: %s version' % sys.argv[0] )
+def main( argv ):
+    if len(argv) != 2:
+        print( 'Usage: %s <version>' % (sys.argv[0],) )
         return
 
     version = sys.argv[1]
+
+    if not check_version( version ):
+        return 1
+
     from_url = 'https://svn.code.sf.net/p/cxx/code/trunk/CXX'
     tag_base_url = 'https://svn.code.sf.net/p/cxx/code/tags'
 
     make_tag( from_url, tag_base_url, version )
 
 if __name__ == '__main__':
-    main()
+    sys.exit( main( sys.argv ) )