-
Notifications
You must be signed in to change notification settings - Fork 788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generated extension functions are weakly typed #108
Comments
thanks! this is definitely a bug. |
So it seems relevant that I'm running this example on Windows (target_pointer_width="64", target_os="windows"), and that the argument type is The problem appears to be here: Lines 121 to 130 in 63a2066
This code was there since it was written in dgrunwald/rust-cpython@55ea6cc#diff-2eab662fc2799e2bdab71b4844e11090R155 I wonder if this whole |
but |
|
Unexpected :) |
Found another similar instance of weak-typedness that happens for a different reason: #[pyfn(m, "take_i32")]
fn take_i32(a: i32) -> PyResult<()> {
println!("my arg is {}", a);
Ok(())
} >>> take_i32(42) # good
my arg is 42
>>> take_i32('42') # good
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required (got type str)
>>> take_i32(42.9) # bad
my arg is 42 This happens because in Lines 48 to 57 in 63a2066
, the call to PyLong_AsLong() is equivalent to calling __int__() method on an object. Strings don't have it but floats do.
|
Neither Python nor Rust has implicit float to integer conversions (they mask programming errors), so it would make sense for the bindings library to disallow them as well. Later there will be tests that such conversions result in TypeError.
In `int_fits_c_long!`, use `PyLong_AsLong(PyNumber_Index(x))` instead of `PyNumber_Index(x)`. In `int_convert_u64_or_i64!`, use `PyLong_As*LongLong(PyNumber_Index(x))` instead of `PyLong_As*LongLong(if PyLong_Check(x) {x} else {PyNumber_Long(x)})`. Along the way, fix memory leak caused by missing `Py_DECREF(num)`. `PyNumber_Index(x)` is the best way to get an integer losslessly: https://docs.python.org/3/reference/datamodel.html#object.__index__ https://docs.python.org/3.5/c-api/number.html#c.PyNumber_Index `PyLong_AsLong(x)` has the problem that it attempts to call `x.__int__()`. Strings don't implement this method, but floats do, so it silently converts floats to integers. https://docs.python.org/3.5/c-api/long.html#c.PyLong_AsLong `PyNumber_Long(x)` is equivalent to `int(x)` call, so not only does it truncate floats, but also attempts to parse strings. https://docs.python.org/3.5/c-api/number.html#c.PyNumber_Long `PyLong_Check(x)` is redundant because it happens inside `PyNumber_Index(x)` anyway: https://github.com/python/cpython/blob/988fb28431d3a3fc5dc6eb657c8a4baacc04d9ce/Objects/abstract.c#L1259
Disallow str/float to int conversions #108
@Vlad-Shcherbina i think this should be fixed now? |
Yes, it's fixed for Python 3. |
Consider the README example:
Here is what happens when this function is called with non-int arguments:
Generally Python functions that expect int argument raise TypeError when fed strings or floats. This helps to catch some programming errors.
I think it would be more consistent if generated extension functions behaved the same way.
The text was updated successfully, but these errors were encountered: