| 1 | //! C API Compatibility Shims |
| 2 | //! |
| 3 | //! Some CPython C API functions added in recent versions of Python are |
| 4 | //! inherently safer to use than older C API constructs. This module |
| 5 | //! exposes functions available on all Python versions that wrap the |
| 6 | //! old C API on old Python versions and wrap the function directly |
| 7 | //! on newer Python versions. |
| 8 | |
| 9 | // Unless otherwise noted, the compatibility shims are adapted from |
| 10 | // the pythoncapi-compat project: https://github.com/python/pythoncapi-compat |
| 11 | |
| 12 | /// Internal helper macro which defines compatibility shims for C API functions, deferring to a |
| 13 | /// re-export when that's available. |
| 14 | macro_rules! compat_function { |
| 15 | ( |
| 16 | originally_defined_for($cfg:meta); |
| 17 | |
| 18 | $(#[$attrs:meta])* |
| 19 | pub unsafe fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty $body:block |
| 20 | ) => { |
| 21 | // Define as a standalone function under docsrs cfg so that this shows as a unique function in the docs, |
| 22 | // not a re-export (the re-export has the wrong visibility) |
| 23 | #[cfg(any(docsrs, not($cfg)))] |
| 24 | #[cfg_attr(docsrs, doc(cfg(all())))] |
| 25 | $(#[$attrs])* |
| 26 | pub unsafe fn $name( |
| 27 | $($arg_names: $arg_types,)* |
| 28 | ) -> $ret $body |
| 29 | |
| 30 | #[cfg(all($cfg, not(docsrs)))] |
| 31 | pub use $crate::$name; |
| 32 | |
| 33 | #[cfg(test)] |
| 34 | paste::paste! { |
| 35 | // Test that the compat function does not overlap with the original function. If the |
| 36 | // cfgs line up, then the the two glob imports will resolve to the same item via the |
| 37 | // re-export. If the cfgs mismatch, then the use of $name will be ambiguous in cases |
| 38 | // where the function is defined twice, and the test will fail to compile. |
| 39 | #[allow(unused_imports)] |
| 40 | mod [<test_ $name _export>] { |
| 41 | use $crate::*; |
| 42 | use $crate::compat::*; |
| 43 | |
| 44 | #[test] |
| 45 | fn test_export() { |
| 46 | let _ = $name; |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | }; |
| 51 | } |
| 52 | |
| 53 | mod py_3_10; |
| 54 | mod py_3_13; |
| 55 | mod py_3_9; |
| 56 | |
| 57 | pub use self::py_3_10::*; |
| 58 | pub use self::py_3_13::*; |
| 59 | pub use self::py_3_9::*; |
| 60 | |