Fix conversion of 'float' and 'double' values (#487)

* Fix conversion of 'float' and 'double' values

Fix problem of conversion 'float' and 'double' values in converter.cs.
As there was a range check both for 'float' and 'double' values, which
are less or greater than its 'MinValue' and 'MaxValue' accordingly,
several values like 'float.NegativeInfinity', 'float.PositiveInfinity'
and the same 'double' values cannot be converted from Python to .NET
values.

Add error check after 'PyFloat_AsDouble' call.
Due to Python C API documentation, method 'PyFloat_AsDouble' can return
'-1.0' upon failure. So it requires error check. This rule forces to
check for error and throw exception in case of error.

Add tests, which cover problem of conversion 'float' and 'double'
values.

Resolves: #486.

* Fix failing 'test_double_conversion' test

Fix incorrect part of 'test_double_conversion' test in test_conversion.py.
An 'OverflowError' was expected for valid values, which represent Python
'inf' and '-inf'.
The problem was identified with support of conversion for Python 'inf'
and '-inf' to .NET System.Double PositiveInfinity and NegativeInfinity.

See also: #487.
This commit is contained in:
Konstantin 2017-06-14 17:18:46 +03:00 коммит произвёл denfromufa
Родитель bfce5e299d
Коммит d39f9f6e0c
6 изменённых файлов: 58 добавлений и 16 удалений

Просмотреть файл

@ -27,6 +27,7 @@
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
- John Burnett ([@johnburnett](https://github.com/johnburnett))
- Luke Stratman ([@lstratman](https://github.com/lstratman))
- Konstantin Posudevskiy ([@konstantin-posudevskiy](https://github.com/konstantin-posudevskiy))
- Matthias Dittrich ([@matthid](https://github.com/matthid))
- Patrick Stewart ([@patstew](https://github.com/patstew))
- Raphael Nestler ([@rnestler](https://github.com/rnestler))

Просмотреть файл

@ -20,6 +20,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
- Fixed crash on exit of the Python interpreter if a python class
derived from a .NET class has a `__namespace__` or `__assembly__`
attribute (#481)
- Fixed conversion of 'float' and 'double' values (#486)
## [2.3.0][] - 2017-03-11

Просмотреть файл

@ -84,6 +84,7 @@
<Compile Include="pyimport.cs" />
<Compile Include="pyinitialize.cs" />
<Compile Include="pyrunstring.cs" />
<Compile Include="TestConverter.cs" />
<Compile Include="TestCustomMarshal.cs" />
<Compile Include="TestExample.cs" />
<Compile Include="TestPyAnsiString.cs" />

Просмотреть файл

@ -0,0 +1,48 @@
using NUnit.Framework;
using Python.Runtime;
namespace Python.EmbeddingTest
{
public class TestConverter
{
[OneTimeSetUp]
public void SetUp()
{
PythonEngine.Initialize();
}
[OneTimeTearDown]
public void Dispose()
{
PythonEngine.Shutdown();
}
[Test]
public void TestConvertSingleToManaged(
[Values(float.PositiveInfinity, float.NegativeInfinity, float.MinValue, float.MaxValue, float.NaN,
float.Epsilon)] float testValue)
{
var pyFloat = new PyFloat(testValue);
object convertedValue;
var converted = Converter.ToManaged(pyFloat.Handle, typeof(float), out convertedValue, false);
Assert.IsTrue(converted);
Assert.IsTrue(((float) convertedValue).Equals(testValue));
}
[Test]
public void TestConvertDoubleToManaged(
[Values(double.PositiveInfinity, double.NegativeInfinity, double.MinValue, double.MaxValue, double.NaN,
double.Epsilon)] double testValue)
{
var pyFloat = new PyFloat(testValue);
object convertedValue;
var converted = Converter.ToManaged(pyFloat.Handle, typeof(double), out convertedValue, false);
Assert.IsTrue(converted);
Assert.IsTrue(((double) convertedValue).Equals(testValue));
}
}
}

Просмотреть файл

@ -770,10 +770,14 @@ namespace Python.Runtime
goto type_error;
}
double dd = Runtime.PyFloat_AsDouble(op);
Runtime.CheckExceptionOccurred();
Runtime.XDecref(op);
if (dd > Single.MaxValue || dd < Single.MinValue)
{
goto overflow;
if (!double.IsInfinity(dd))
{
goto overflow;
}
}
result = (float)dd;
return true;
@ -785,11 +789,8 @@ namespace Python.Runtime
goto type_error;
}
double d = Runtime.PyFloat_AsDouble(op);
Runtime.CheckExceptionOccurred();
Runtime.XDecref(op);
if (d > Double.MaxValue || d < Double.MinValue)
{
goto overflow;
}
result = d;
return true;
}

Просмотреть файл

@ -466,17 +466,6 @@ def test_double_conversion():
with pytest.raises(TypeError):
ConversionTest().DoubleField = None
with pytest.raises(OverflowError):
ConversionTest().DoubleField = 1.7976931348623159e308
with pytest.raises(OverflowError):
ConversionTest().DoubleField = -1.7976931348623159e308
with pytest.raises(OverflowError):
_ = System.Double(1.7976931348623159e308)
with pytest.raises(OverflowError):
_ = System.Double(-1.7976931348623159e308)
def test_decimal_conversion():