Overloaded C++ function Python wrappers now raise a TypeError instead of NotImplementedError

Occurs when the types passed are incorrect. This change means
there is now consistency with non-overloaded function wrappers which have always
raised TypeError when the incorrect types are passed.

See issue #1293
diff --git a/CHANGES.current b/CHANGES.current
index 46bb5a9..64a2e65 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,27 @@
 Version 4.0.0 (in progress)
 ===========================
 
+2018-07-31: wsfulton
+            [Python] #1293 Overloaded C++ function wrappers now raise a TypeError instead
+            of NotImplementedError when the types passed are incorrect. This change means
+            there is now consistency with non-overloaded function wrappers which have always
+            raised TypeError when the incorrect types are passed. The error message remains
+            the same and is for example now:
+
+              TypeError: Wrong number or type of arguments for overloaded function 'f'.
+                Possible C/C++ prototypes are:
+                  f(int)
+                  f(char const *)
+
+            instead of:
+
+              NotImplementedError: Wrong number or type of arguments for overloaded function 'f'.
+                Possible C/C++ prototypes are:
+                  f(int)
+                  f(char const *)
+
+            *** POTENTIAL INCOMPATIBILITY ***
+
 2018-06-23: wsfulton
             [Python] #718 Fix pythonnondynamic feature for modern classes
 
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html
index 1a2fd9e..5969060 100644
--- a/Doc/Manual/Python.html
+++ b/Doc/Manual/Python.html
@@ -4894,7 +4894,7 @@
 Traceback (most recent call last):
   File "runme.py", line 3, in >module<
     example.foo(["foo", "bar", "spam", "1"])
-NotImplementedError: Wrong number or type of arguments for overloaded function 'foo'.
+TypeError: Wrong number or type of arguments for overloaded function 'foo'.
   Possible C/C++ prototypes are:
     foo(int, char **)
     foo()
diff --git a/Examples/test-suite/python/li_std_string_extra_runme.py b/Examples/test-suite/python/li_std_string_extra_runme.py
index 9835eaa..53d2bdc 100644
--- a/Examples/test-suite/python/li_std_string_extra_runme.py
+++ b/Examples/test-suite/python/li_std_string_extra_runme.py
@@ -95,14 +95,18 @@
 
 try:
     li_std_string_extra.test_value_basic_overload([x])
-    raise RuntimeError, "should throw NotImplementedError"
-except NotImplementedError:
+    raise RuntimeError, "should throw TypeError"
+except TypeError as e:
+    if str(e).find("Possible C/C++ prototypes are:") == -1:
+        raise RuntimeError("Incorrect error message text:\n{}".format(e))
     pass
 
 try:
     li_std_string_extra.test_value_basic_overload([123])
-    raise RuntimeError, "should throw NotImplementedError"
-except NotImplementedError:
+    raise RuntimeError, "should throw TypeError"
+except TypeError as e:
+    if str(e).find("Possible C/C++ prototypes are:") == -1:
+        raise RuntimeError("Incorrect error message text:\n{}".format(e))
     pass
 
 # Global variables
diff --git a/Examples/test-suite/python/primitive_types_runme.py b/Examples/test-suite/python/primitive_types_runme.py
index b2060a0..c5009f6 100644
--- a/Examples/test-suite/python/primitive_types_runme.py
+++ b/Examples/test-suite/python/primitive_types_runme.py
@@ -549,14 +549,9 @@
             if t.ovr_str(val + delta) == name:
                 raise RuntimeError, "bad " + name + " typemap"
             if val == limit:
-                # Should raise NotImplementedError here since this is the largest integral type
-                raise RuntimeError, "bad " + name + " typemap"
-        except NotImplementedError:
-            # NotImplementedError is expected only if this is the most extreme type
-            if val != limit:
+                # Should raise TypeError here since this is the largest integral type
                 raise RuntimeError, "bad " + name + " typemap"
         except TypeError:
-            # TypeError is raised instead if swig is run with -O or -fastdispatch
             if val != limit:
                 raise RuntimeError, "bad " + name + " typemap"
 
diff --git a/Examples/test-suite/python/varargs_runme.py b/Examples/test-suite/python/varargs_runme.py
index 7105ba8..277ea75 100644
--- a/Examples/test-suite/python/varargs_runme.py
+++ b/Examples/test-suite/python/varargs_runme.py
@@ -30,7 +30,5 @@
 try:
     varargs.test_plenty("Hello", 1, 2, 3)
     raise RuntimeError
-except NotImplementedError:
-    pass
 except TypeError:
     pass
diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
index 89a9d2a..f7ec22a 100755
--- a/Source/Modules/python.cxx
+++ b/Source/Modules/python.cxx
@@ -2645,7 +2645,7 @@
 	Delete(fulldecl);
       } while ((sibl = Getattr(sibl, "sym:nextSibling")));
       Append(f->code, "fail:\n");
-      Printf(f->code, "  SWIG_SetErrorMsg(PyExc_NotImplementedError,"
+      Printf(f->code, "  SWIG_SetErrorMsg(PyExc_TypeError,"
 	     "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\"  Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
       Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0");
       Delete(protoTypes);