From cd14a4a724dc86916a11e85b8789bbbcca53cb78 Mon Sep 17 00:00:00 2001
From: Matthias Dittrich <matthi.d@gmail.com>
Date: Thu, 26 May 2016 23:55:53 +0200
Subject: [PATCH 1/6] fix NullReferenceException when using null on a argument
 list.

---
 src/runtime/classderived.cs | 2 +-
 src/runtime/converter.cs    | 4 ++--
 src/runtime/pyobject.cs     | 2 +-
 src/runtime/pythonengine.cs | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs
index ea1181731..1fd8e04d1 100644
--- a/src/runtime/classderived.cs
+++ b/src/runtime/classderived.cs
@@ -786,7 +786,7 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, Objec
                         PyObject[] pyargs = new PyObject[args.Length];
                         for (int i = 0; i < args.Length; ++i)
                         {
-                            pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i].GetType()));
+                            pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i]?.GetType()));
                             disposeList.Add(pyargs[i]);
                         }
 
diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs
index cdc610c2c..66ddfad5d 100644
--- a/src/runtime/converter.cs
+++ b/src/runtime/converter.cs
@@ -228,7 +228,7 @@ internal static IntPtr ToPython(Object value, Type type)
                         {
                             foreach (object o in (IEnumerable)value)
                             {
-                                using (var p = new PyObject(ToPython(o, o.GetType())))
+                                using (var p = new PyObject(ToPython(o, o?.GetType())))
                                     resultlist.Append(p);
                             }
                             Runtime.Incref(resultlist.Handle);
@@ -962,7 +962,7 @@ public static class ConverterExtension
     {
         public static PyObject ToPython(this object o)
         {
-            return new PyObject(Converter.ToPython(o, o.GetType()));
+            return new PyObject(Converter.ToPython(o, o?.GetType()));
         }
     }
 }
\ No newline at end of file
diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs
index 42b8d71b4..685ffd1de 100644
--- a/src/runtime/pyobject.cs
+++ b/src/runtime/pyobject.cs
@@ -972,7 +972,7 @@ private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs)
                 }
                 else
                 {
-                    ptr = Converter.ToPython(inargs[i], inargs[i].GetType());
+                    ptr = Converter.ToPython(inargs[i], inargs[i]?.GetType());
                 }
                 if (Runtime.PyTuple_SetItem(argtuple, i, ptr) < 0)
                     throw new PythonException();
diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs
index 7e37d6211..cf9bfb9ee 100644
--- a/src/runtime/pythonengine.cs
+++ b/src/runtime/pythonengine.cs
@@ -487,7 +487,7 @@ public static KeywordArguments kw(params object[] kv)
                 if (kv[i + 1] is PyObject)
                     value = ((PyObject)kv[i + 1]).Handle;
                 else
-                    value = Converter.ToPython(kv[i + 1], kv[i + 1].GetType());
+                    value = Converter.ToPython(kv[i + 1], kv[i + 1]?.GetType());
                 if (Runtime.PyDict_SetItemString(dict.Handle, (string)kv[i], value) != 0)
                     throw new ArgumentException(string.Format("Cannot add key '{0}' to dictionary.", (string)kv[i]));
                 if (!(kv[i + 1] is PyObject))

From 87e1df38c92610e7d31129001796f23495f2aabe Mon Sep 17 00:00:00 2001
From: Matthias Dittrich <matthi.d@gmail.com>
Date: Thu, 26 May 2016 23:56:42 +0200
Subject: [PATCH 2/6] Fix NotSupportedException when using the project in an F#
 interactive (maybe C# interactive as well).

---
 src/runtime/moduleobject.cs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs
index 738985598..c2ddf564b 100644
--- a/src/runtime/moduleobject.cs
+++ b/src/runtime/moduleobject.cs
@@ -35,7 +35,10 @@ public ModuleObject(string name) : base()
             string docstring = "Namespace containing types from the following assemblies:\n\n";
             foreach (Assembly a in AssemblyManager.GetAssemblies(name))
             {
-                filename = a.Location;
+                if (!a.IsDynamic && a.Location != null)
+                {
+                    filename = a.Location;
+                }
                 docstring += "- " + a.FullName + "\n";
             }
 

From 8effe30d6cad5d5c0e55a1b5489ebeb59e441f9f Mon Sep 17 00:00:00 2001
From: Matthias Dittrich <matthi.d@gmail.com>
Date: Sat, 4 Jun 2016 13:11:58 +0200
Subject: [PATCH 3/6] add test for #182

---
 src/tests/runtests.py                   |  1 +
 src/tests/test_suite/__init__.py        | 10 ++++++++++
 src/tests/test_suite/_missing_import.py |  2 ++
 src/tests/test_suite/test_import.py     | 16 ++++++++++++++++
 4 files changed, 29 insertions(+)
 create mode 100644 src/tests/test_suite/__init__.py
 create mode 100644 src/tests/test_suite/_missing_import.py
 create mode 100644 src/tests/test_suite/test_import.py

diff --git a/src/tests/runtests.py b/src/tests/runtests.py
index 3a7bde07b..660d3442d 100644
--- a/src/tests/runtests.py
+++ b/src/tests/runtests.py
@@ -18,6 +18,7 @@
     # other test modules that import System.Windows.Forms
     # run first. They must not do module level import/AddReference()
     # of the System.Windows.Forms namespace.
+    'test_suite',
     'test_event',
     'test_constructors',
     'test_enum',
diff --git a/src/tests/test_suite/__init__.py b/src/tests/test_suite/__init__.py
new file mode 100644
index 000000000..8e7f206e0
--- /dev/null
+++ b/src/tests/test_suite/__init__.py
@@ -0,0 +1,10 @@
+import unittest
+
+__all__ = ['test_suite']
+
+from .test_import import test_suite as import_tests
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTests((import_tests(),))
+    return suite
\ No newline at end of file
diff --git a/src/tests/test_suite/_missing_import.py b/src/tests/test_suite/_missing_import.py
new file mode 100644
index 000000000..629ff95be
--- /dev/null
+++ b/src/tests/test_suite/_missing_import.py
@@ -0,0 +1,2 @@
+
+import this_package_should_never_exist_ever
\ No newline at end of file
diff --git a/src/tests/test_suite/test_import.py b/src/tests/test_suite/test_import.py
new file mode 100644
index 000000000..b6d155af3
--- /dev/null
+++ b/src/tests/test_suite/test_import.py
@@ -0,0 +1,16 @@
+import unittest
+
+class ImportTests(unittest.TestCase):
+    """Test the import statement."""
+
+    def testRealtiveMissingImport(self):
+        """Test that a relative missing import doesn't crash. Some modules use this to check if a package is installed (realtive import in the site-packages folder"""
+        try:
+            from . import _missing_import
+        except ImportError:
+            pass
+
+
+def test_suite():
+    return unittest.makeSuite(ImportTests)
+

From 65626c3c5f8e82e7b51cccf92a86d51eb0dab444 Mon Sep 17 00:00:00 2001
From: Matthias Dittrich <matthi.d@gmail.com>
Date: Sat, 4 Jun 2016 14:59:45 +0200
Subject: [PATCH 4/6] add test for using null like 'None' for default
 arguments. See 35cd5fa

---
 src/testing/Python.Test.csproj        |  2 ++
 src/testing/callbacktest.cs           | 31 +++++++++++++++++++++++++++
 src/tests/test_suite/__init__.py      |  2 ++
 src/tests/test_suite/test_callback.py | 30 ++++++++++++++++++++++++++
 4 files changed, 65 insertions(+)
 create mode 100644 src/testing/callbacktest.cs
 create mode 100644 src/tests/test_suite/test_callback.py

diff --git a/src/testing/Python.Test.csproj b/src/testing/Python.Test.csproj
index 354a6eae6..56efda8e3 100644
--- a/src/testing/Python.Test.csproj
+++ b/src/testing/Python.Test.csproj
@@ -108,6 +108,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="arraytest.cs" />
+    <Compile Include="callbacktest.cs" />
     <Compile Include="classtest.cs" />
     <Compile Include="constructortests.cs" />
     <Compile Include="conversiontest.cs" />
@@ -127,6 +128,7 @@
     <Compile Include="subclasstest.cs" />
   </ItemGroup>
   <ItemGroup>
+    <Reference Include="Microsoft.CSharp" />
     <Reference Include="System" />
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
diff --git a/src/testing/callbacktest.cs b/src/testing/callbacktest.cs
new file mode 100644
index 000000000..81389289d
--- /dev/null
+++ b/src/testing/callbacktest.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Python.Test
+{
+    //========================================================================
+    // Tests callbacks into python code.
+    //========================================================================
+
+    public class CallbackTest
+    {
+        public string Call_simpleDefaultArg_WithNull(string moduleName)
+        {
+            using (Runtime.Py.GIL())
+            {
+                dynamic module = Runtime.Py.Import(moduleName);
+                return module.simpleDefaultArg(null);
+            }
+        }
+        public string Call_simpleDefaultArg_WithEmptyArgs(string moduleName)
+        {
+            using (Runtime.Py.GIL())
+            {
+                dynamic module = Runtime.Py.Import(moduleName);
+                return module.simpleDefaultArg();
+            }
+        }
+    }
+}
diff --git a/src/tests/test_suite/__init__.py b/src/tests/test_suite/__init__.py
index 8e7f206e0..1ca730d7b 100644
--- a/src/tests/test_suite/__init__.py
+++ b/src/tests/test_suite/__init__.py
@@ -3,8 +3,10 @@
 __all__ = ['test_suite']
 
 from .test_import import test_suite as import_tests
+from .test_callback import test_suite as callback_tests
 
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTests((import_tests(),))
+    suite.addTests((callback_tests(),))
     return suite
\ No newline at end of file
diff --git a/src/tests/test_suite/test_callback.py b/src/tests/test_suite/test_callback.py
new file mode 100644
index 000000000..16c45914d
--- /dev/null
+++ b/src/tests/test_suite/test_callback.py
@@ -0,0 +1,30 @@
+import unittest, sys
+import clr
+
+this_module = sys.modules[__name__]
+clr.AddReference("Python.Test")
+import Python.Test as Test
+from Python.Test import CallbackTest
+test_instance = CallbackTest()
+
+def simpleDefaultArg(arg = 'test'):
+    return arg
+
+class CallbackTests(unittest.TestCase):
+    """Test that callbacks from C# into python work."""
+
+    def testDefaultForNull(self):
+        """Test that C# can use null for an optional python argument"""
+        retVal = test_instance.Call_simpleDefaultArg_WithNull(__name__)
+        pythonRetVal = simpleDefaultArg(None)
+        self.assertEquals(retVal, pythonRetVal)
+
+    def testDefaultForNone(self):
+        """Test that C# can use no argument for an optional python argument"""
+        retVal = test_instance.Call_simpleDefaultArg_WithEmptyArgs(__name__)
+        pythonRetVal = simpleDefaultArg()
+        self.assertEquals(retVal, pythonRetVal)
+
+def test_suite():
+    return unittest.makeSuite(CallbackTests)
+

From 4b08abd6f6819ed0bc678312f2d589c5ad3495c1 Mon Sep 17 00:00:00 2001
From: Matthias Dittrich <matthi.d@gmail.com>
Date: Sat, 4 Jun 2016 17:11:27 +0200
Subject: [PATCH 5/6] Workaround mono bug, see
 https://bugzilla.xamarin.com/show_bug.cgi?id=41509 and
 https://github.com/pythonnet/pythonnet/pull/219

---
 src/runtime/pyobject.cs | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs
index 685ffd1de..ab0c8021f 100644
--- a/src/runtime/pyobject.cs
+++ b/src/runtime/pyobject.cs
@@ -939,7 +939,7 @@ public override bool TryGetMember(GetMemberBinder binder, out object result)
         {
             if (this.HasAttr(binder.Name))
             {
-                result = this.GetAttr(binder.Name);
+                result = CheckNone(this.GetAttr(binder.Name));
                 return true;
             }
             else
@@ -999,7 +999,7 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o
                 try
                 {
                     GetArgs(args, out pyargs, out kwargs);
-                    result = InvokeMethod(binder.Name, pyargs, kwargs);
+                    result = CheckNone(InvokeMethod(binder.Name, pyargs, kwargs));
                 }
                 finally
                 {
@@ -1023,7 +1023,7 @@ public override bool TryInvoke(InvokeBinder binder, object[] args, out object re
                 try
                 {
                     GetArgs(args, out pyargs, out kwargs);
-                    result = Invoke(pyargs, kwargs);
+                    result = CheckNone(Invoke(pyargs, kwargs));
                 }
                 finally
                 {
@@ -1133,10 +1133,26 @@ public override bool TryBinaryOperation(BinaryOperationBinder binder, Object arg
                     result = null;
                     return false;
             }
-            result = new PyObject(res);
+            result = CheckNone(new PyObject(res));
+
             return true;
         }
 
+        // Workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=41509
+        // See https://github.com/pythonnet/pythonnet/pull/219
+        private static object CheckNone(PyObject pyObj)
+        {
+            if (pyObj != null)
+            {
+                if (pyObj.obj == Runtime.PyNone)
+                {
+                    return null;
+                }
+            }
+
+            return pyObj;
+        }
+
         public override bool TryUnaryOperation(UnaryOperationBinder binder, out Object result)
         {
             int r;
@@ -1170,7 +1186,7 @@ public override bool TryUnaryOperation(UnaryOperationBinder binder, out Object r
                     result = null;
                     return false;
             }
-            result = new PyObject(res);
+            result = CheckNone(new PyObject(res));
             return true;
         }
     }

From c07e9fe30f6798d1cabc375921291d66583a3c6f Mon Sep 17 00:00:00 2001
From: Matthias Dittrich <matthi.d@gmail.com>
Date: Sat, 23 Jul 2016 07:50:59 +0200
Subject: [PATCH 6/6] whitespace to trigger appveyor

---
 src/runtime/pyobject.cs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs
index ab0c8021f..308e71ffb 100644
--- a/src/runtime/pyobject.cs
+++ b/src/runtime/pyobject.cs
@@ -1134,7 +1134,6 @@ public override bool TryBinaryOperation(BinaryOperationBinder binder, Object arg
                     return false;
             }
             result = CheckNone(new PyObject(res));
-
             return true;
         }