Allow decoders to decode Python types derived from primitives
Environment
- Pythonnet version: 3.0.2
- Python version: not relevant for this issue
- Operating System: not relevant for this issue
- .NET Runtime: not relevant for this issue
Details
-
We have used the preview version in the past and wrapped it so that we are able to update the package and change against interfaces for future releases. One part of it is converting numpy types. By default such types are not supported anymore in the release version and it seems to be recommended to use codecs instead. I registered a codec (same as pandanet) but
PyObject.As<double>()does not convertPyType = <class 'numpy.int32'>with the help of the codec. By debugging it never hits the PyObjectConversions.TryDecode because double it is not equal to "object type" and not one of the "DecodableByUserTypes".TODO
to reproduce:
import numpy as np
numpyArray = np.array([1, 2])
// C# part
var value = numpyArray.GetItem(i)
var valueAsT = value.As<double>(); // fails
Whish:
- solution to handle such a case i.e. by configuring hooks or use the existing codec approach to convert before it hits the usual
ToPrimitive(...)function which fails.
Related https://github.com/pythonnet/pythonnet/issues/1887
There are few workarounds for this:
- Explicitly call
.item(). E.g.Math.Abs(np.int64(42))--> fail;Math.Abs(np.int64(42).item())--> OK - It seems that your
GetItemis a custom method. It could in principle perform the conversion and returndoubleinstead ofPyObject. This is the approach I have in https://www.nuget.org/packages/LostTech.NumPy/
As for the suggestion itself, my major concern about adding codecs for primitive types is that they will be invoked on any attempt to convert to a .NET primitive, which in many cases will have a noticeable performance impact.
There are few workarounds for this:
- Explicitly call
.item(). E.g.Math.Abs(np.int64(42))--> fail;Math.Abs(np.int64(42).item())--> OK- It seems that your
GetItemis a custom method. It could in principle perform the conversion and returndoubleinstead ofPyObject. This is the approach I have in https://www.nuget.org/packages/LostTech.NumPy/
- Seems to be a change to all existing usages -> breaking, without changing all consumers
- PyObject.GetItem(int) is an existing function in this pythonnet library
As for the suggestion itself, my major concern about adding codecs for primitive types is that they will be invoked on any attempt to convert to a .NET primitive, which in many cases will have a noticeable performance impact.
How about adding a flag:
if(IsPrimitiveCodecsEnabled) // no noticable performance issue with single bool check
{
var isSucess = TryDecode(...) // via codec
if(isSuccess){return;}
}
ToPrimitive(...)
return;
We will not be adding flags, as every flag adds a whole new dimension to the testing matrix.
@Bluubb can you tell more about your use case? Is there a reason you can not make a function to replace As<double>()?