From 9d8559158b708b1121f643876b663ac1035f40a4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 19 Sep 2020 11:23:00 -0400 Subject: [PATCH] Hack __text_signature__ back to working with abi3 --- src/pyclass.rs | 16 ++++++++++++++++ tests/test_text_signature.rs | 14 +++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/pyclass.rs b/src/pyclass.rs index 0b5f8db4..aa21881b 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -256,6 +256,22 @@ fn tp_init_additional(type_object: *mut ffi::PyTypeObject) { // Just patch the type objects for the things there's no // PyType_FromSpec API for... there's no reason this should work, // except for that it does and we have tests. + + // Running this causes PyPy to segfault. + #[cfg(not(PyPy))] + if T::DESCRIPTION != "\0" { + unsafe { + // Until CPython 3.10, tp_doc was treated specially for heap-types, + // and it removed the text_signature value from it. We go in after + // the fact and replace tp_doc with something that _does_ include + // the text_signature value! + ffi::PyObject_Free((*type_object).tp_doc as _); + let data = ffi::PyObject_Malloc(T::DESCRIPTION.len()); + data.copy_from(T::DESCRIPTION.as_ptr() as _, T::DESCRIPTION.len()); + (*type_object).tp_doc = data as _; + } + } + if let Some(buffer) = T::buffer_methods() { unsafe { (*(*type_object).tp_as_buffer).bf_getbuffer = buffer.as_ref().bf_getbuffer; diff --git a/tests/test_text_signature.rs b/tests/test_text_signature.rs index 929bb2eb..feca3f3e 100644 --- a/tests/test_text_signature.rs +++ b/tests/test_text_signature.rs @@ -31,10 +31,8 @@ fn class_with_docs() { py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); } -// Ignored because heap types don't have working __text_signature__: -// https://github.com/python/cpython/blob/master/Objects/typeobject.c#L864-L870 #[test] -#[ignore] +#[cfg_attr(Py_LIMITED_API, ignore)] fn class_with_docs_and_signature() { /// docs line1 #[pyclass] @@ -69,10 +67,8 @@ fn class_with_docs_and_signature() { ); } -// Ignored because heap types don't have working __text_signature__: -// https://github.com/python/cpython/blob/master/Objects/typeobject.c#L864-L870 #[test] -#[ignore] +#[cfg_attr(Py_LIMITED_API, ignore)] fn class_with_signature() { #[pyclass] #[text_signature = "(a, b=None, *, c=42)"] @@ -92,7 +88,11 @@ fn class_with_signature() { let py = gil.python(); let typeobj = py.get_type::(); - py_assert!(py, typeobj, "typeobj.__doc__ is None"); + py_assert!( + py, + typeobj, + "typeobj.__doc__ is None or typeobj.__doc__ == ''" + ); py_assert!( py, typeobj,