Skip to content

Commit ba7485a

Browse files
authored
Merge branch 'master' into patch-1
2 parents 2e87ba7 + 25e66f0 commit ba7485a

22 files changed

+634
-412
lines changed

AUTHORS.md

+2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@
2727
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
2828
- John Burnett ([@johnburnett](https://github.com/johnburnett))
2929
- Luke Stratman ([@lstratman](https://github.com/lstratman))
30+
- Konstantin Posudevskiy ([@konstantin-posudevskiy](https://github.com/konstantin-posudevskiy))
3031
- Matthias Dittrich ([@matthid](https://github.com/matthid))
3132
- Patrick Stewart ([@patstew](https://github.com/patstew))
3233
- Raphael Nestler ([@rnestler](https://github.com/rnestler))
34+
- Rickard Holmberg ([@rickardraysearch](https://github.com/rickardraysearch))
3335
- Sam Winstanley ([@swinstanley](https://github.com/swinstanley))
3436
- Sean Freitag ([@cowboygneox](https://github.com/cowboygneox))
3537
- Serge Weinstock ([@sweinst](https://github.com/sweinst))

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
2121
- Fixed crash on exit of the Python interpreter if a python class
2222
derived from a .NET class has a `__namespace__` or `__assembly__`
2323
attribute (#481)
24+
- Fixed conversion of 'float' and 'double' values (#486)
25+
- Fixed 'clrmethod' for python 2 (#492)
26+
- Fixed double calling of constructor when deriving from .NET class (#495)
27+
2428

2529
## [2.3.0][] - 2017-03-11
2630

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# pythonnet - Python for .NET
22

3+
[![Join the chat at https://gitter.im/pythonnet/pythonnet](https://badges.gitter.im/pythonnet/pythonnet.svg)](https://gitter.im/pythonnet/pythonnet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4+
35
[![appveyor shield][]](https://ci.appveyor.com/project/pythonnet/pythonnet/branch/master)
46
[![travis shield][]](https://travis-ci.org/pythonnet/pythonnet)
57
[![codecov shield][]](https://codecov.io/github/pythonnet/pythonnet)
@@ -87,6 +89,10 @@ int32
8789
[ 6. 10. 12.]
8890
```
8991

92+
Information on installation, FAQ, troubleshooting, debugging, and projects using pythonnet can be found in the Wiki:
93+
94+
https://github.com/pythonnet/pythonnet/wiki
95+
9096
[appveyor shield]: https://img.shields.io/appveyor/ci/pythonnet/pythonnet/master.svg?label=AppVeyor
9197

9298
[codecov shield]: https://img.shields.io/codecov/c/github/pythonnet/pythonnet/master.svg?label=Codecov

src/embed_tests/Python.EmbeddingTest.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
<Compile Include="pyimport.cs" />
8585
<Compile Include="pyinitialize.cs" />
8686
<Compile Include="pyrunstring.cs" />
87+
<Compile Include="TestConverter.cs" />
8788
<Compile Include="TestCustomMarshal.cs" />
8889
<Compile Include="TestExample.cs" />
8990
<Compile Include="TestPyAnsiString.cs" />

src/embed_tests/TestConverter.cs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using NUnit.Framework;
2+
using Python.Runtime;
3+
4+
namespace Python.EmbeddingTest
5+
{
6+
public class TestConverter
7+
{
8+
[OneTimeSetUp]
9+
public void SetUp()
10+
{
11+
PythonEngine.Initialize();
12+
}
13+
14+
[OneTimeTearDown]
15+
public void Dispose()
16+
{
17+
PythonEngine.Shutdown();
18+
}
19+
20+
[Test]
21+
public void TestConvertSingleToManaged(
22+
[Values(float.PositiveInfinity, float.NegativeInfinity, float.MinValue, float.MaxValue, float.NaN,
23+
float.Epsilon)] float testValue)
24+
{
25+
var pyFloat = new PyFloat(testValue);
26+
27+
object convertedValue;
28+
var converted = Converter.ToManaged(pyFloat.Handle, typeof(float), out convertedValue, false);
29+
30+
Assert.IsTrue(converted);
31+
Assert.IsTrue(((float) convertedValue).Equals(testValue));
32+
}
33+
34+
[Test]
35+
public void TestConvertDoubleToManaged(
36+
[Values(double.PositiveInfinity, double.NegativeInfinity, double.MinValue, double.MaxValue, double.NaN,
37+
double.Epsilon)] double testValue)
38+
{
39+
var pyFloat = new PyFloat(testValue);
40+
41+
object convertedValue;
42+
var converted = Converter.ToManaged(pyFloat.Handle, typeof(double), out convertedValue, false);
43+
44+
Assert.IsTrue(converted);
45+
Assert.IsTrue(((double) convertedValue).Equals(testValue));
46+
}
47+
}
48+
}

src/embed_tests/TestPythonEngineProperties.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public void SetProgramName()
146146
[Test]
147147
public void SetPythonPath()
148148
{
149-
if (Runtime.Runtime.pyversion == "2.7")
149+
if (Runtime.Runtime._pyversion == "2.7")
150150
{
151151
// Assert.Skip outputs as a warning (ie. pending to fix)
152152
Assert.Pass();
@@ -166,7 +166,7 @@ public void SetPythonPath()
166166
[Test]
167167
public void SetPythonPathExceptionOn27()
168168
{
169-
if (Runtime.Runtime.pyversion != "2.7")
169+
if (Runtime.Runtime._pyversion != "2.7")
170170
{
171171
Assert.Pass();
172172
}

src/embed_tests/TestRuntime.cs

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using NUnit.Framework;
33
using Python.Runtime;
44

@@ -47,5 +47,46 @@ public static void RefCountTest()
4747

4848
Runtime.Runtime.Py_Finalize();
4949
}
50+
51+
[Test]
52+
public static void PyCheck_Iter_PyObject_IsIterable_Test()
53+
{
54+
Runtime.Runtime.Py_Initialize();
55+
56+
// Tests that a python list is an iterable, but not an iterator
57+
var pyList = Runtime.Runtime.PyList_New(0);
58+
Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyList));
59+
Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyList));
60+
61+
// Tests that a python list iterator is both an iterable and an iterator
62+
var pyListIter = Runtime.Runtime.PyObject_GetIter(pyList);
63+
Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyListIter));
64+
Assert.IsTrue(Runtime.Runtime.PyIter_Check(pyListIter));
65+
66+
// Tests that a python float is neither an iterable nor an iterator
67+
var pyFloat = Runtime.Runtime.PyFloat_FromDouble(2.73);
68+
Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(pyFloat));
69+
Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyFloat));
70+
71+
Runtime.Runtime.Py_Finalize();
72+
}
73+
74+
[Test]
75+
public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
76+
{
77+
Runtime.Runtime.Py_Initialize();
78+
79+
// Create an instance of threading.Lock, which is one of the very few types that does not have the
80+
// TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
81+
var threading = Runtime.Runtime.PyImport_ImportModule("threading");
82+
var threadingDict = Runtime.Runtime.PyModule_GetDict(threading);
83+
var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
84+
var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType, Runtime.Runtime.PyTuple_New(0));
85+
86+
Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
87+
Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));
88+
89+
Runtime.Runtime.Py_Finalize();
90+
}
5091
}
5192
}

src/runtime/CustomMarshaler.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ public static int GetUnicodeByteLength(IntPtr p)
9191
var len = 0;
9292
while (true)
9393
{
94-
int c = Runtime.UCS == 2
94+
int c = Runtime._UCS == 2
9595
? Marshal.ReadInt16(p, len * 2)
9696
: Marshal.ReadInt32(p, len * 4);
9797

9898
if (c == 0)
9999
{
100-
return len * Runtime.UCS;
100+
return len * Runtime._UCS;
101101
}
102102
checked
103103
{
@@ -163,7 +163,7 @@ public override IntPtr MarshalManagedToNative(object managedObj)
163163
}
164164

165165
int totalStrLength = argv.Sum(arg => arg.Length + 1);
166-
int memSize = argv.Length * IntPtr.Size + totalStrLength * Runtime.UCS;
166+
int memSize = argv.Length * IntPtr.Size + totalStrLength * Runtime._UCS;
167167

168168
IntPtr mem = Marshal.AllocHGlobal(memSize);
169169
try

src/runtime/Python.Runtime.csproj

+6-3
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
<SignAssembly>false</SignAssembly>
2121
<AssemblyOriginatorKeyFile>..\pythonnet.snk</AssemblyOriginatorKeyFile>
2222
</PropertyGroup>
23-
<PropertyGroup Condition=" '$(Platform)' == 'x86'">
23+
<!--We can relax binding to platform because code references no any platform dependent assemblies-->
24+
<!--This will allows to use any build of this assebly as a compile ref assebly-->
25+
<!--<PropertyGroup Condition=" '$(Platform)' == 'x86'">
2426
<PlatformTarget>x86</PlatformTarget>
2527
</PropertyGroup>
2628
<PropertyGroup Condition=" '$(Platform)' == 'x64'">
2729
<PlatformTarget>x64</PlatformTarget>
28-
</PropertyGroup>
30+
</PropertyGroup>-->
2931
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseMono'">
3032
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON2;PYTHON27;UCS4</DefineConstants>
3133
<Optimize>true</Optimize>
@@ -136,6 +138,7 @@
136138
<Compile Include="runtime.cs" />
137139
<Compile Include="typemanager.cs" />
138140
<Compile Include="typemethod.cs" />
141+
<Compile Include="Util.cs" />
139142
</ItemGroup>
140143
<ItemGroup Condition=" '$(PythonInteropFile)' != '' ">
141144
<Compile Include="$(PythonInteropFile)" />
@@ -164,4 +167,4 @@
164167
<Copy SourceFiles="$(TargetAssembly)" DestinationFolder="$(PythonBuildDir)" />
165168
<!--Copy SourceFiles="$(TargetAssemblyPdb)" Condition="Exists('$(TargetAssemblyPdb)')" DestinationFolder="$(PythonBuildDir)" /-->
166169
</Target>
167-
</Project>
170+
</Project>

src/runtime/Util.cs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Python.Runtime
5+
{
6+
internal class Util
7+
{
8+
internal static Int64 ReadCLong(IntPtr tp, int offset)
9+
{
10+
// On Windows, a C long is always 32 bits.
11+
if (Runtime.IsWindows || Runtime.Is32Bit)
12+
{
13+
return Marshal.ReadInt32(tp, offset);
14+
}
15+
else
16+
{
17+
return Marshal.ReadInt64(tp, offset);
18+
}
19+
}
20+
21+
internal static void WriteCLong(IntPtr type, int offset, Int64 flags)
22+
{
23+
if (Runtime.IsWindows || Runtime.Is32Bit)
24+
{
25+
Marshal.WriteInt32(type, offset, (Int32)(flags & 0xffffffffL));
26+
}
27+
else
28+
{
29+
Marshal.WriteInt64(type, offset, flags);
30+
}
31+
}
32+
}
33+
}

src/runtime/classderived.cs

+1-35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Reflection;
@@ -808,7 +808,6 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, objec
808808
obj,
809809
args);
810810

811-
var disposeList = new List<PyObject>();
812811
CLRObject self = null;
813812
IntPtr gs = Runtime.PyGILState_Ensure();
814813
try
@@ -821,42 +820,9 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, objec
821820
// object to be collected.
822821
FieldInfo fi = obj.GetType().GetField("__pyobj__");
823822
fi.SetValue(obj, self);
824-
825-
Runtime.XIncref(self.pyHandle);
826-
var pyself = new PyObject(self.pyHandle);
827-
disposeList.Add(pyself);
828-
829-
Runtime.XIncref(Runtime.PyNone);
830-
var pynone = new PyObject(Runtime.PyNone);
831-
disposeList.Add(pynone);
832-
833-
// call __init__
834-
PyObject init = pyself.GetAttr("__init__", pynone);
835-
disposeList.Add(init);
836-
if (init.Handle != Runtime.PyNone)
837-
{
838-
// if __init__ hasn't been overridden then it will be a managed object
839-
ManagedType managedMethod = ManagedType.GetManagedObject(init.Handle);
840-
if (null == managedMethod)
841-
{
842-
var pyargs = new PyObject[args.Length];
843-
for (var i = 0; i < args.Length; ++i)
844-
{
845-
pyargs[i] = new PyObject(Converter.ToPython(args[i], args[i]?.GetType()));
846-
disposeList.Add(pyargs[i]);
847-
}
848-
849-
disposeList.Add(init.Invoke(pyargs));
850-
}
851-
}
852823
}
853824
finally
854825
{
855-
foreach (PyObject x in disposeList)
856-
{
857-
x?.Dispose();
858-
}
859-
860826
// Decrement the python object's reference count.
861827
// This doesn't actually destroy the object, it just sets the reference to this object
862828
// to be a weak reference and it will be destroyed when the C# object is destroyed.

src/runtime/clrobject.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Runtime.InteropServices;
33

44
namespace Python.Runtime
@@ -11,7 +11,7 @@ internal CLRObject(object ob, IntPtr tp)
1111
{
1212
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
1313

14-
var flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
14+
long flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
1515
if ((flags & TypeFlags.Subclass) != 0)
1616
{
1717
IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.DictOffset(tp));

src/runtime/converter.cs

+6-5
Original file line numberDiff line numberDiff line change
@@ -770,10 +770,14 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo
770770
goto type_error;
771771
}
772772
double dd = Runtime.PyFloat_AsDouble(op);
773+
Runtime.CheckExceptionOccurred();
773774
Runtime.XDecref(op);
774775
if (dd > Single.MaxValue || dd < Single.MinValue)
775776
{
776-
goto overflow;
777+
if (!double.IsInfinity(dd))
778+
{
779+
goto overflow;
780+
}
777781
}
778782
result = (float)dd;
779783
return true;
@@ -785,11 +789,8 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo
785789
goto type_error;
786790
}
787791
double d = Runtime.PyFloat_AsDouble(op);
792+
Runtime.CheckExceptionOccurred();
788793
Runtime.XDecref(op);
789-
if (d > Double.MaxValue || d < Double.MinValue)
790-
{
791-
goto overflow;
792-
}
793794
result = d;
794795
return true;
795796
}

src/runtime/managedtype.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Runtime.InteropServices;
33

44
namespace Python.Runtime
@@ -28,7 +28,7 @@ internal static ManagedType GetManagedObject(IntPtr ob)
2828
tp = ob;
2929
}
3030

31-
var flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
31+
var flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
3232
if ((flags & TypeFlags.Managed) != 0)
3333
{
3434
IntPtr op = tp == ob
@@ -63,7 +63,7 @@ internal static bool IsManagedType(IntPtr ob)
6363
tp = ob;
6464
}
6565

66-
var flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
66+
var flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
6767
if ((flags & TypeFlags.Managed) != 0)
6868
{
6969
return true;

0 commit comments

Comments
 (0)