eclipse-basyx / basyx-python-sdk

MIT License
61 stars 28 forks source link

Integer value is not accepted for Double value type #227

Open mhrimaz opened 10 months ago

mhrimaz commented 10 months ago
from basyx.aas import model
import basyx.aas.adapter.json
property = model.Property(
    id_short='ExampleProperty',  # Identifying string of the element within the submodel namespace
    value_type=model.datatypes.Double,  # Data type of the value
    value=1,  # Value of the property
)

this minimal example does not work and produce the following error:

TypeError: 1 cannot be trivially casted into float

the code only works if it is explicitly a float value:

from basyx.aas import model
import basyx.aas.adapter.json
property = model.Property(
    id_short='ExampleProperty',  # Identifying string of the element within the submodel namespace
    value_type=model.datatypes.Double,  # Data type of the value
    value=1.0,  # Value of the property
)

is that a feature or bug?

s-heppner commented 10 months ago

From the documentation of model.datatypes.trivial_cast:

The main purpose of this function is to allow AAS :class:Properties <basyx.aas.model.submodel.Property> (and similar objects with XSD-type values) to take Python literal values and convert them to their XSD type. However, we want to stay strongly typed, so we only allow this type-cast if it is trivial to do, i.e. does not change the value's semantics. Examples, where this holds true:

  • int → :class:~basyx.aas.model.datatypes.Int (if the value is in the expected range)
  • bytes → :class:~basyx.aas.model.datatypes.Base64Binary
  • datetime.date → :class:~basyx.aas.model.datatypes.Date

Yet, it is not allowed to cast float → :class:basyx.aas.model.datatypes.Int

I would therefore say, this is a feature, not a bug, considering the first value you put in is actually an integer, that has different semantics, whereas Double and floats argually have more similar semantics.

mhrimaz commented 10 months ago

@s-heppner It depends how you interpret different semantics.
In general, it might be a little tricky to handle XSD datatypes natively in python as there are many corner cases. However, 1 in this example shouldn't cause any problem and this behaviour is kinda unexpected.

https://www.w3.org/TR/xmlschema11-2/#double:

The ·lexical space· of double is the set of all decimal numerals with or without a decimal point, numerals in scientific (exponential) notation, and the ·literals· 'INF', '+INF', '-INF', and 'NaN'

https://www.w3.org/TR/xmlschema-2/#double :

For example, -1E4, 1267.43233E12, 12.78e-2, 12 , -0, 0 and INF are all legal literals for double.

s-heppner commented 10 months ago

I see your point. I have been thinking about this problem, but I have not really come to a good solution. I'll mark this Issue as a bug and we'll discuss it with the team.

jkhsjdhjs commented 9 months ago

My take is that python numbers are simply different from XML numbers, so we cannot apply the same rules here. While in XML 1 is a valid double, this isn't the case for python, where 1 is of type int, but 1., 1.0 and float(1) are of type float.

Allowing 1 for Float and Double would make it a bit more convenient, it would also make it inconsistent, as the type would be changed for int -> float casts but not for other casts.