Skip to content
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

ffi: update object.rs for 3.13 #4447

Merged
merged 9 commits into from
Aug 21, 2024
Merged

Conversation

davidhewitt
Copy link
Member

Related to #4379, #4265

I audited object.rs for differences against 3.13 and applied all the differences I found here. At the same time I also removed all _Py private APIs.

I found a free threading detail in PyType_HasFeature which we needed to account for (atomic load), cc @ngoldbaum

(Will push CHANGELOG later, out of time right now...)

@davidhewitt davidhewitt changed the title clean up parsing and docs for module macro options ffi: update object.rs for 3.13 Aug 17, 2024
@davidhewitt
Copy link
Member Author

davidhewitt commented Aug 17, 2024

Not sure how I got the commit message / PR title wrong originally; fat finger error while being hurried by family probably 🙈

pub unsafe fn PyType_HasFeature(t: *mut PyTypeObject, f: c_ulong) -> c_int {
(((*t).tp_flags & f) != 0) as c_int
#[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
let flags = (*ty).tp_flags.load(Ordering::Relaxed);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, totally missed this.


extern "C" {
#[cfg(Py_3_13)]
#[cfg_attr(PyPy, link_name = "PyPy_GetConstant")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there's no harm and it will probably work this way, but it seems a little premature to add code to support PyPy 3.13, which won't be coming out for quite a while, if ever.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I have gone back and forth on these "future" bindings for PyPy, but I've also had so many cases where the link_name attribute has randomly missing creating compile errors for users on PyPy I just think it's slightly better this way round now.

arg1: *mut PyObject,
arg2: *mut PyObject,
arg3: *mut *mut PyObject,
) -> c_int;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if the pattern of doing a getitem and then clearing the error afterwards shows up in the PyO3 codebase, but this will be a nice thing to use if it does show up. It's much faster to not create the error object if you don't actually need it.

let local = (*ob).ob_ref_local.load(Relaxed);
if local == _Py_IMMORTAL_REFCNT_LOCAL {
return _Py_IMMORTAL_REFCNT;
#[cfg(Py_GIL_DISABLED)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this pattern of exposing the function once and then using per-config blocks inside the function to do the per-config implementation. Much cleaner than having multiple copies of the signature. And it looks like it plays nicer with the doc build too.

@@ -123,38 +131,45 @@ pub struct PyVarObject {
pub ob_size: Py_ssize_t,
}

// skipped _PyVarObject_CAST
// skipped private _PyVarObject_CAST

#[inline]
pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int {
(x == y).into()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally unrelated to this PR and a bit of a minor corner case, but this is wrong on pypy, see pypy/pypy#4044

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging, worth fixing anyway while I'm here!

Copy link
Member

@mejrs mejrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks; here is what I could review on my phone :)

@@ -0,0 +1,20 @@
#[cfg(Py_GIL_DISABLED)]
mod atomic_c_ulong {
pub(crate) struct GetAtomicCULong<const SIZE: usize>();
Copy link
Member

@mejrs mejrs Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the size in bits or in bytes? I would naively expect the latter, but have no opinion. Maybe we should call it "width" if we want the former.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I was thinking it's easier to think in bits here but size_of() returns bytes, so this is currently bugged 👍

Renamed to WIDTH 👍

@@ -0,0 +1 @@
Add Python 3.13 FFI definitions `PyObject_GetOptionalAttr`, `PyObject_GetOptionalAttrString`, `PyObject_HasAttrWithError`, `PyObject_HasAttrStringWithError`, `Py_CONSTANT_*` constants, `Py_GetConstant`, `Py_GetConstantBorowed`, and `PyType_GetModuleByDef`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Borrowed?

@davidhewitt
Copy link
Member Author

I will merge this to unblock forward progress; if there is more to do here then I can follow up. Thanks both for reviews!

@davidhewitt davidhewitt added this pull request to the merge queue Aug 21, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Aug 21, 2024
pyo3-ffi/src/object.rs Outdated Show resolved Hide resolved
Co-authored-by: Alex Gaynor <[email protected]>
@davidhewitt davidhewitt added this pull request to the merge queue Aug 21, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Aug 21, 2024
@davidhewitt davidhewitt added this pull request to the merge queue Aug 21, 2024
Merged via the queue into PyO3:main with commit 2f5b45e Aug 21, 2024
43 checks passed
@davidhewitt davidhewitt deleted the object-3-13 branch August 21, 2024 20:02
@ngoldbaum
Copy link
Contributor

ngoldbaum commented Aug 24, 2024

I'm not sure why the tests didn't catch it when this was merged, but git bisect says this PR is causing the test failures with cargo test --features=abi3 on main with 3.13:

failures:

---- binary_arithmetic stdout ----
thread 'binary_arithmetic' panicked at tests/test_arithmetics.rs:265:9:
Did not raise PyTypeError: ()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- rich_comparisons_python_3_type_error stdout ----
thread 'rich_comparisons_python_3_type_error' panicked at tests/test_arithmetics.rs:568:9:
Did not raise PyTypeError: ()

---- return_not_implemented::reverse_arith stdout ----
thread 'return_not_implemented::reverse_arith' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__radd__(Other()) is NotImplemented

---- return_not_implemented::ordering stdout ----
thread 'return_not_implemented::ordering' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__lt__(Other()) is NotImplemented

---- return_not_implemented::arith stdout ----
thread 'return_not_implemented::arith' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__add__(Other()) is NotImplemented

---- return_not_implemented::equality stdout ----
thread 'return_not_implemented::equality' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__eq__(Other()) is NotImplemented

---- return_not_implemented::bitwise stdout ----
thread 'return_not_implemented::bitwise' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__and__(Other()) is NotImplemented

---- return_not_implemented::inplace_arith stdout ----
thread 'return_not_implemented::inplace_arith' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__iadd__(Other()) is NotImplemented

---- return_not_implemented::inplace_bitwise stdout ----
thread 'return_not_implemented::inplace_bitwise' panicked at tests/test_arithmetics.rs:669:13:
class Other: pass
assert c2.__iand__(Other()) is NotImplemented


failures:
    binary_arithmetic
    return_not_implemented::arith
    return_not_implemented::bitwise
    return_not_implemented::equality
    return_not_implemented::inplace_arith
    return_not_implemented::inplace_bitwise
    return_not_implemented::ordering
    return_not_implemented::reverse_arith
    rich_comparisons_python_3_type_error

test result: FAILED. 6 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s

error: test failed, to rerun pass `--test test_arithmetics`

@davidhewitt
Copy link
Member Author

3.13 doesn't block merges yet, but you're right, I will investigate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants