From 57412f1a2943dae1a34ef3ecae3f8c1381ab2b9a Mon Sep 17 00:00:00 2001 From: messense Date: Tue, 12 Apr 2022 17:04:40 +0800 Subject: [PATCH 1/8] Install cargo-xwin from PyPI to speedup CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb2ef435..07013451 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -278,7 +278,7 @@ jobs: run: | sudo apt-get install -y mingw-w64 llvm rustup target add x86_64-pc-windows-gnu x86_64-pc-windows-msvc - which cargo-xwin > /dev/null || cargo install cargo-xwin + python -m pip install cargo-xwin cargo build --manifest-path examples/maturin-starter/Cargo.toml --features abi3 --target x86_64-pc-windows-gnu cargo xwin build --manifest-path examples/maturin-starter/Cargo.toml --features abi3 --target x86_64-pc-windows-msvc - name: Test cross compile to Windows with maturin From a1f97f164deebae5175f2986e43cd18369d296be Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 1 Apr 2022 00:01:43 +0800 Subject: [PATCH 2/8] Add PyTzInfoAccess --- CHANGELOG.md | 1 + pytests/src/datetime.rs | 12 +++++- pytests/tests/test_datetime.py | 2 + src/types/datetime.rs | 68 ++++++++++++++++++++++++++++++++++ src/types/mod.rs | 1 + 5 files changed, 83 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 984461e3..52c060b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282) - Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294) +- Added `PyTzInfoAccess`. [#2263](https://github.com/PyO3/pyo3/pull/2263) ### Changed diff --git a/pytests/src/datetime.rs b/pytests/src/datetime.rs index f526ae0a..fc67b247 100644 --- a/pytests/src/datetime.rs +++ b/pytests/src/datetime.rs @@ -3,7 +3,7 @@ use pyo3::prelude::*; use pyo3::types::{ PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTuple, - PyTzInfo, + PyTzInfo, PyTzInfoAccess, }; #[pyfunction] @@ -179,6 +179,16 @@ fn datetime_from_timestamp<'p>( PyDateTime::from_timestamp(py, ts, tz) } +#[pyfunction] +fn get_datetime_tzinfo(dt: &PyDateTime) -> Option<&PyTzInfo> { + dt.get_tzinfo() +} + +#[pyfunction] +fn get_time_tzinfo(dt: &PyTime) -> Option<&PyTzInfo> { + dt.get_tzinfo() +} + #[pyclass(extends=PyTzInfo)] pub struct TzClass {} diff --git a/pytests/tests/test_datetime.py b/pytests/tests/test_datetime.py index e70504e7..d4c1b60e 100644 --- a/pytests/tests/test_datetime.py +++ b/pytests/tests/test_datetime.py @@ -114,6 +114,7 @@ def test_time(args, kwargs): assert act == exp assert act.tzinfo is exp.tzinfo + assert rdt.get_time_tzinfo(act) == exp.tzinfo @given(t=st.times()) @@ -194,6 +195,7 @@ def test_datetime(args, kwargs): assert act == exp assert act.tzinfo is exp.tzinfo + assert rdt.get_datetime_tzinfo(act) == exp.tzinfo @given(dt=st.datetimes()) diff --git a/src/types/datetime.rs b/src/types/datetime.rs index c4053011..68eaa829 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -5,6 +5,8 @@ use crate::err::PyResult; use crate::ffi; +#[cfg(PyPy)] +use crate::ffi::datetime::{PyDateTime_FromTimestamp, PyDate_FromTimestamp}; use crate::ffi::{ PyDateTime_CAPI, PyDateTime_FromTimestamp, PyDateTime_IMPORT, PyDate_FromTimestamp, }; @@ -22,6 +24,7 @@ use crate::ffi::{ PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND, }; +use crate::instance::PyNativeType; use crate::types::PyTuple; use crate::{AsPyPointer, PyAny, PyObject, Python, ToPyObject}; use std::os::raw::c_int; @@ -160,6 +163,16 @@ pub trait PyTimeAccess { fn get_fold(&self) -> bool; } +/// Trait for accessing the components of a struct containing a tzinfo. +pub trait PyTzInfoAccess { + /// Returns the tzinfo (which may be None). + /// + /// Implementations should conform to the upstream documentation: + /// + /// + fn get_tzinfo(&self) -> Option<&PyTzInfo>; +} + /// Bindings around `datetime.date` #[repr(transparent)] pub struct PyDate(PyAny); @@ -354,6 +367,19 @@ impl PyTimeAccess for PyDateTime { } } +impl PyTzInfoAccess for PyDateTime { + fn get_tzinfo(&self) -> Option<&PyTzInfo> { + let ptr = self.as_ptr() as *mut ffi::PyDateTime_DateTime; + unsafe { + if (*ptr).hastzinfo != 0 { + Some(self.py().from_borrowed_ptr((*ptr).tzinfo)) + } else { + None + } + } + } +} + /// Bindings for `datetime.time` #[repr(transparent)] pub struct PyTime(PyAny); @@ -439,6 +465,19 @@ impl PyTimeAccess for PyTime { } } +impl PyTzInfoAccess for PyTime { + fn get_tzinfo(&self) -> Option<&PyTzInfo> { + let ptr = self.as_ptr() as *mut ffi::PyDateTime_Time; + unsafe { + if (*ptr).hastzinfo != 0 { + Some(self.py().from_borrowed_ptr((*ptr).tzinfo)) + } else { + None + } + } + } +} + /// Bindings for `datetime.tzinfo` /// /// This is an abstract base class and should not be constructed directly. @@ -524,4 +563,33 @@ mod tests { assert!(b.unwrap().get_fold()); }); } + + #[cfg(not(PyPy))] + #[test] + fn test_get_tzinfo() { + crate::Python::with_gil(|py| { + use crate::conversion::ToPyObject; + use crate::types::{PyDateTime, PyTime, PyTzInfoAccess}; + + let datetime = py.import("datetime").map_err(|e| e.print(py)).unwrap(); + let timezone = datetime.getattr("timezone").unwrap(); + let utc = timezone.getattr("utc").unwrap().to_object(py); + + let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap(); + + assert!(dt.get_tzinfo().unwrap().eq(&utc).unwrap()); + + let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap(); + + assert!(dt.get_tzinfo().is_none()); + + let t = PyTime::new(py, 0, 0, 0, 0, Some(&utc)).unwrap(); + + assert!(t.get_tzinfo().unwrap().eq(&utc).unwrap()); + + let t = PyTime::new(py, 0, 0, 0, 0, None).unwrap(); + + assert!(t.get_tzinfo().is_none()); + }); + } } diff --git a/src/types/mod.rs b/src/types/mod.rs index 192fa80a..ad79d062 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -11,6 +11,7 @@ pub use self::complex::PyComplex; #[cfg(not(Py_LIMITED_API))] pub use self::datetime::{ PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTzInfo, + PyTzInfoAccess, }; pub use self::dict::{IntoPyDict, PyDict}; pub use self::floatob::PyFloat; From 58b70812743d25d64ee02c96c7d3b933f8cb9951 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Tue, 12 Apr 2022 17:51:30 +0200 Subject: [PATCH 3/8] Use more robust hexadecimal escaping of interpreter configuration. --- CHANGELOG.md | 1 + pyo3-build-config/src/impl_.rs | 78 +++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 984461e3..afb180e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289) +- Fix directory names starting with the letter `n` breaking serialization of the interpreter configuration on Windows since PyO3 0.16.3. [#2299](https://github.com/PyO3/pyo3/pull/2299) ## [0.16.3] - 2022-04-05 diff --git a/pyo3-build-config/src/impl_.rs b/pyo3-build-config/src/impl_.rs index d34cc7a1..b5f6aa39 100644 --- a/pyo3-build-config/src/impl_.rs +++ b/pyo3-build-config/src/impl_.rs @@ -366,7 +366,7 @@ print("mingw", get_platform().startswith("mingw")) #[doc(hidden)] pub fn from_cargo_dep_env() -> Option> { cargo_env_var("DEP_PYTHON_PYO3_CONFIG") - .map(|buf| InterpreterConfig::from_reader(buf.replace("\\n", "\n").as_bytes())) + .map(|buf| InterpreterConfig::from_reader(&*unescape(&buf))) } #[doc(hidden)] @@ -464,11 +464,7 @@ print("mingw", get_platform().startswith("mingw")) let mut buf = Vec::new(); self.to_writer(&mut buf)?; // escape newlines in env var - if let Ok(config) = str::from_utf8(&buf) { - println!("cargo:PYO3_CONFIG={}", config.replace('\n', "\\n")); - } else { - bail!("unable to emit interpreter config to link env for downstream use"); - } + println!("cargo:PYO3_CONFIG={}", escape(&buf)); Ok(()) } @@ -1688,9 +1684,42 @@ pub fn make_interpreter_config() -> Result { } } +fn escape(bytes: &[u8]) -> String { + let mut escaped = String::with_capacity(2 * bytes.len()); + + for byte in bytes { + const LUT: &[u8; 16] = b"0123456789abcdef"; + + escaped.push(LUT[(byte >> 4) as usize] as char); + escaped.push(LUT[(byte & 0x0F) as usize] as char); + } + + escaped +} + +fn unescape(escaped: &str) -> Vec { + assert!(escaped.len() % 2 == 0, "invalid hex encoding"); + + let mut bytes = Vec::with_capacity(escaped.len() / 2); + + for chunk in escaped.as_bytes().chunks_exact(2) { + fn unhex(hex: u8) -> u8 { + match hex { + b'a'..=b'f' => hex - b'a' + 10, + b'0'..=b'9' => hex - b'0', + _ => panic!("invalid hex encoding"), + } + } + + bytes.push(unhex(chunk[0]) << 4 | unhex(chunk[1])); + } + + bytes +} + #[cfg(test)] mod tests { - use std::{io::Cursor, iter::FromIterator}; + use std::iter::FromIterator; use target_lexicon::triple; use super::*; @@ -1713,10 +1742,7 @@ mod tests { let mut buf: Vec = Vec::new(); config.to_writer(&mut buf).unwrap(); - assert_eq!( - config, - InterpreterConfig::from_reader(Cursor::new(buf)).unwrap() - ); + assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap()); // And some different options, for variety @@ -1744,17 +1770,37 @@ mod tests { let mut buf: Vec = Vec::new(); config.to_writer(&mut buf).unwrap(); - assert_eq!( - config, - InterpreterConfig::from_reader(Cursor::new(buf)).unwrap() - ); + assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap()); + } + + #[test] + fn test_config_file_roundtrip_with_escaping() { + let config = InterpreterConfig { + abi3: true, + build_flags: BuildFlags::default(), + pointer_width: Some(32), + executable: Some("executable".into()), + implementation: PythonImplementation::CPython, + lib_name: Some("lib_name".into()), + lib_dir: Some("lib_dir\\n".into()), + shared: true, + version: MINIMUM_SUPPORTED_VERSION, + suppress_build_script_link_lines: true, + extra_build_script_lines: vec!["cargo:test1".to_string(), "cargo:test2".to_string()], + }; + let mut buf: Vec = Vec::new(); + config.to_writer(&mut buf).unwrap(); + + let buf = unescape(&escape(&buf)); + + assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap()); } #[test] fn test_config_file_defaults() { // Only version is required assert_eq!( - InterpreterConfig::from_reader(Cursor::new("version=3.7")).unwrap(), + InterpreterConfig::from_reader("version=3.7".as_bytes()).unwrap(), InterpreterConfig { version: PythonVersion { major: 3, minor: 7 }, implementation: PythonImplementation::CPython, From ae7e1f5ee947a570d9e44e9dd97028d0f37ad64c Mon Sep 17 00:00:00 2001 From: Sergey Kvachonok Date: Mon, 11 Apr 2022 14:45:16 +0300 Subject: [PATCH 4/8] pyo3-build-config: Build "abi3" extensions without an interpreter Support compiling portable "abi3" extension modules even when the build host Python interpreter configuration is not available or the discovered Python interpreter version is not supported. Maturin already implements this by building "abi3" extension wheels with `PYO3_NO_PYTHON` environment veriable set for cargo when an `abi3-py3*` feature is detected. Closes #2292 --- CHANGELOG.md | 1 + Cargo.toml | 2 +- guide/src/building_and_distribution.md | 2 + pyo3-build-config/Cargo.toml | 4 ++ pyo3-build-config/src/impl_.rs | 77 ++++++++++++++++++++------ 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c2b74a3..96e8428c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Allow to compile "abi3" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293) - Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288) - Improved performance of failing calls to `FromPyObject::extract` which is common when functions accept multiple distinct types. [#2279](https://github.com/PyO3/pyo3/pull/2279) diff --git a/Cargo.toml b/Cargo.toml index 99655923..833ac0ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ pyproto = ["pyo3-macros/pyproto"] # Use this feature when building an extension module. # It tells the linker to keep the python symbols unresolved, # so that the module can also be used with statically linked python interpreters. -extension-module = ["pyo3-ffi/extension-module"] +extension-module = ["pyo3-build-config/extension-module", "pyo3-ffi/extension-module"] # Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more. abi3 = ["pyo3-build-config/abi3", "pyo3-ffi/abi3", "pyo3-macros/abi3"] diff --git a/guide/src/building_and_distribution.md b/guide/src/building_and_distribution.md index 0fda63b3..ce69030c 100644 --- a/guide/src/building_and_distribution.md +++ b/guide/src/building_and_distribution.md @@ -157,6 +157,8 @@ PyO3 is only able to link your extension module to api3 version up to and includ #### Building `abi3` extensions without a Python interpreter As an advanced feature, you can build PyO3 wheel without calling Python interpreter with the environment variable `PYO3_NO_PYTHON` set. +Also, if the build host Python interpreter is not found or is too old or otherwise unusable, +PyO3 will still attempt to compile `abi3` extension modules after displaying a warning message. On Unix-like systems this works unconditionally; on Windows you must also set the `RUSTFLAGS` environment variable to contain `-L native=/path/to/python/libs` so that the linker can find `python3.lib`. diff --git a/pyo3-build-config/Cargo.toml b/pyo3-build-config/Cargo.toml index 86ffa36e..7449b1f9 100644 --- a/pyo3-build-config/Cargo.toml +++ b/pyo3-build-config/Cargo.toml @@ -26,6 +26,10 @@ default = [] # script. If this feature isn't enabled, the build script no-ops. resolve-config = [] +# This feature is enabled by pyo3 when building an extension module. +extension-module = [] + +# These features are enabled by pyo3 when building Stable ABI extension modules. abi3 = [] abi3-py37 = ["abi3-py38"] abi3-py38 = ["abi3-py39"] diff --git a/pyo3-build-config/src/impl_.rs b/pyo3-build-config/src/impl_.rs index d34cc7a1..07bd5102 100644 --- a/pyo3-build-config/src/impl_.rs +++ b/pyo3-build-config/src/impl_.rs @@ -233,6 +233,13 @@ print("mingw", get_platform().startswith("mingw")) "#; let output = run_python_script(interpreter.as_ref(), SCRIPT)?; let map: HashMap = parse_script_output(&output); + + ensure!( + !map.is_empty(), + "broken Python interpreter: {}", + interpreter.as_ref().display() + ); + let shared = map["shared"].as_str() == "True"; let version = PythonVersion { @@ -682,14 +689,14 @@ pub fn is_extension_module() -> bool { /// Checks if we need to link to `libpython` for the current build target. /// -/// Must be called from a crate PyO3 build script. +/// Must be called from a PyO3 crate build script. pub fn is_linking_libpython() -> bool { is_linking_libpython_for_target(&target_triple_from_env()) } /// Checks if we need to link to `libpython` for the target. /// -/// Must be called from a crate PyO3 build script. +/// Must be called from a PyO3 crate build script. fn is_linking_libpython_for_target(target: &Triple) -> bool { target.operating_system == OperatingSystem::Windows || target.environment == Environment::Android @@ -697,6 +704,18 @@ fn is_linking_libpython_for_target(target: &Triple) -> bool { || !is_extension_module() } +/// Checks if we need to discover the Python library directory +/// to link the extension module binary. +/// +/// Must be called from a PyO3 crate build script. +fn require_libdir_for_target(target: &Triple) -> bool { + let is_generating_libpython = cfg!(feature = "python3-dll-a") + && target.operating_system == OperatingSystem::Windows + && is_abi3(); + + is_linking_libpython_for_target(target) && !is_generating_libpython +} + /// Configuration needed by PyO3 to cross-compile for a target platform. /// /// Usually this is collected from the environment (i.e. `PYO3_CROSS_*` and `CARGO_CFG_TARGET_*`) @@ -1646,6 +1665,18 @@ pub fn find_interpreter() -> Result { } } +/// Locates and extracts the build host Python interpreter configuration. +/// +/// Lowers the configured Python version to `abi3_version` if required. +fn get_host_interpreter(abi3_version: Option) -> Result { + let interpreter_path = find_interpreter()?; + + let mut interpreter_config = InterpreterConfig::from_interpreter(interpreter_path)?; + interpreter_config.fixup_for_abi3_version(abi3_version)?; + + Ok(interpreter_config) +} + /// Generates an interpreter config suitable for cross-compilation. /// /// This must be called from PyO3's build script, because it relies on environment variables such as @@ -1666,26 +1697,40 @@ pub fn make_cross_compile_config() -> Result> { /// Only used by `pyo3-build-config` build script. #[allow(dead_code, unused_mut)] pub fn make_interpreter_config() -> Result { + let host = Triple::host(); let abi3_version = get_abi3_version(); + // See if we can safely skip the Python interpreter configuration detection. + // Unix "abi3" extension modules can usually be built without any interpreter. + let need_interpreter = abi3_version.is_none() || require_libdir_for_target(&host); + if have_python_interpreter() { - let mut interpreter_config = InterpreterConfig::from_interpreter(find_interpreter()?)?; - interpreter_config.fixup_for_abi3_version(abi3_version)?; - Ok(interpreter_config) - } else if let Some(version) = abi3_version { - let host = Triple::host(); - let mut interpreter_config = default_abi3_config(&host, version); - - // Auto generate python3.dll import libraries for Windows targets. - #[cfg(feature = "python3-dll-a")] - { - interpreter_config.lib_dir = self::abi3_import_lib::generate_abi3_import_lib(&host)?; + match get_host_interpreter(abi3_version) { + Ok(interpreter_config) => return Ok(interpreter_config), + // Bail if the interpreter configuration is required to build. + Err(e) if need_interpreter => return Err(e), + _ => { + // Fall back to the "abi3" defaults just as if `PYO3_NO_PYTHON` + // environment variable was set. + warn!("Compiling without a working Python interpreter."); + } } - - Ok(interpreter_config) } else { - bail!("An abi3-py3* feature must be specified when compiling without a Python interpreter.") + ensure!( + abi3_version.is_some(), + "An abi3-py3* feature must be specified when compiling without a Python interpreter." + ); + }; + + let mut interpreter_config = default_abi3_config(&host, abi3_version.unwrap()); + + // Auto generate python3.dll import libraries for Windows targets. + #[cfg(feature = "python3-dll-a")] + { + interpreter_config.lib_dir = self::abi3_import_lib::generate_abi3_import_lib(&host)?; } + + Ok(interpreter_config) } #[cfg(test)] From 0d0089ea292760a8a3a3d5279ca0d6de74dcef6a Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Wed, 13 Apr 2022 09:02:45 +0200 Subject: [PATCH 5/8] Remove redundant use statements and add missing calls to add_function in datetime test. --- CHANGELOG.md | 2 +- pytests/src/datetime.rs | 2 ++ src/types/datetime.rs | 5 +---- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52c060b1..69633969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282) - Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294) -- Added `PyTzInfoAccess`. [#2263](https://github.com/PyO3/pyo3/pull/2263) +- Added `PyTzInfoAccess` for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263) ### Changed diff --git a/pytests/src/datetime.rs b/pytests/src/datetime.rs index fc67b247..b21d3e69 100644 --- a/pytests/src/datetime.rs +++ b/pytests/src/datetime.rs @@ -224,6 +224,8 @@ pub fn datetime(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(make_datetime, m)?)?; m.add_function(wrap_pyfunction!(get_datetime_tuple, m)?)?; m.add_function(wrap_pyfunction!(datetime_from_timestamp, m)?)?; + m.add_function(wrap_pyfunction!(get_datetime_tzinfo, m)?)?; + m.add_function(wrap_pyfunction!(get_time_tzinfo, m)?)?; // Functions not supported by PyPy #[cfg(not(PyPy))] diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 68eaa829..90782774 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -4,11 +4,8 @@ //! documentation](https://docs.python.org/3/library/datetime.html) use crate::err::PyResult; -use crate::ffi; -#[cfg(PyPy)] -use crate::ffi::datetime::{PyDateTime_FromTimestamp, PyDate_FromTimestamp}; use crate::ffi::{ - PyDateTime_CAPI, PyDateTime_FromTimestamp, PyDateTime_IMPORT, PyDate_FromTimestamp, + self, PyDateTime_CAPI, PyDateTime_FromTimestamp, PyDateTime_IMPORT, PyDate_FromTimestamp, }; #[cfg(not(PyPy))] use crate::ffi::{PyDateTime_DATE_GET_FOLD, PyDateTime_TIME_GET_FOLD}; From 01e2a553df7babe5b5df4d28b0a9ec96eb35cf11 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Thu, 14 Apr 2022 07:42:53 +0100 Subject: [PATCH 6/8] noxfile: sort authors case-insensitively --- noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index 216bc56d..e399a79c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -124,7 +124,7 @@ def contributors(session: nox.Session) -> None: else: break - authors = sorted(list(authors)) + authors = sorted(list(authors), key=lambda author: author.lower()) for author in authors: print(f"@{author}") From d2caa056e9aacc46374139ef491d112cb8af1a25 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sun, 10 Apr 2022 19:48:26 +0200 Subject: [PATCH 7/8] release: 0.16.4 --- CHANGELOG.md | 12 ++++++++---- Cargo.toml | 8 ++++---- README.md | 4 ++-- examples/Cargo.toml | 2 +- examples/decorator/.template/pre-script.rhai | 2 +- examples/maturin-starter/.template/pre-script.rhai | 2 +- .../.template/pre-script.rhai | 2 +- examples/word-count/.template/pre-script.rhai | 2 +- pyo3-build-config/Cargo.toml | 2 +- pyo3-ffi/Cargo.toml | 4 ++-- pyo3-macros-backend/Cargo.toml | 2 +- pyo3-macros/Cargo.toml | 4 ++-- 12 files changed, 25 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d565a662..2a320cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.16.4] - 2022-04-14 + ### Added +- Add `PyTzInfoAccess` trait for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263) - Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282) - Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294) -- Added `PyTzInfoAccess` for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263) ### Changed -- Allow to compile "abi3" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293) -- Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288) - Improved performance of failing calls to `FromPyObject::extract` which is common when functions accept multiple distinct types. [#2279](https://github.com/PyO3/pyo3/pull/2279) +- Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288) +- Allow to compile "abi3" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293) ### Fixed +- Crates depending on PyO3 can collect code coverage via LLVM instrumentation using stable Rust. [#2286](https://github.com/PyO3/pyo3/pull/2286) - Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289) - Fix directory names starting with the letter `n` breaking serialization of the interpreter configuration on Windows since PyO3 0.16.3. [#2299](https://github.com/PyO3/pyo3/pull/2299) @@ -1148,7 +1151,8 @@ Yanked - Initial release -[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.16.3...HEAD +[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.16.4...HEAD +[0.16.3]: https://github.com/pyo3/pyo3/compare/v0.16.3...v0.16.4 [0.16.3]: https://github.com/pyo3/pyo3/compare/v0.16.2...v0.16.3 [0.16.2]: https://github.com/pyo3/pyo3/compare/v0.16.1...v0.16.2 [0.16.1]: https://github.com/pyo3/pyo3/compare/v0.16.0...v0.16.1 diff --git a/Cargo.toml b/Cargo.toml index 833ac0ac..23df80c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3" -version = "0.16.3" +version = "0.16.4" description = "Bindings to Python interpreter" authors = ["PyO3 Project and Contributors "] readme = "README.md" @@ -19,10 +19,10 @@ libc = "0.2.62" parking_lot = ">= 0.11, < 0.13" # ffi bindings to the python interpreter, split into a seperate crate so they can be used independently -pyo3-ffi = { path = "pyo3-ffi", version = "=0.16.3" } +pyo3-ffi = { path = "pyo3-ffi", version = "=0.16.4" } # support crates for macros feature -pyo3-macros = { path = "pyo3-macros", version = "=0.16.3", optional = true } +pyo3-macros = { path = "pyo3-macros", version = "=0.16.4", optional = true } indoc = { version = "1.0.3", optional = true } unindent = { version = "0.1.4", optional = true } @@ -50,7 +50,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.61" [build-dependencies] -pyo3-build-config = { path = "pyo3-build-config", version = "0.16.3", features = ["resolve-config"] } +pyo3-build-config = { path = "pyo3-build-config", version = "0.16.4", features = ["resolve-config"] } [features] default = ["macros", "pyproto"] diff --git a/README.md b/README.md index f7e55dc1..01637bbc 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ name = "string_sum" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.16.3", features = ["extension-module"] } +pyo3 = { version = "0.16.4", features = ["extension-module"] } ``` **`src/lib.rs`** @@ -132,7 +132,7 @@ Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like th ```toml [dependencies.pyo3] -version = "0.16.3" +version = "0.16.4" features = ["auto-initialize"] ``` diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 816dcce7..a46e14f5 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -5,7 +5,7 @@ publish = false edition = "2018" [dev-dependencies] -pyo3 = { version = "0.16.3", path = "..", features = ["auto-initialize", "extension-module"] } +pyo3 = { version = "0.16.4", path = "..", features = ["auto-initialize", "extension-module"] } [[example]] name = "decorator" diff --git a/examples/decorator/.template/pre-script.rhai b/examples/decorator/.template/pre-script.rhai index caad7593..7ba10b00 100644 --- a/examples/decorator/.template/pre-script.rhai +++ b/examples/decorator/.template/pre-script.rhai @@ -1,4 +1,4 @@ -variable::set("PYO3_VERSION", "0.16.3"); +variable::set("PYO3_VERSION", "0.16.4"); file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/pyproject.toml", "pyproject.toml"); file::rename(".template/tox.ini", "tox.ini"); diff --git a/examples/maturin-starter/.template/pre-script.rhai b/examples/maturin-starter/.template/pre-script.rhai index caad7593..7ba10b00 100644 --- a/examples/maturin-starter/.template/pre-script.rhai +++ b/examples/maturin-starter/.template/pre-script.rhai @@ -1,4 +1,4 @@ -variable::set("PYO3_VERSION", "0.16.3"); +variable::set("PYO3_VERSION", "0.16.4"); file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/pyproject.toml", "pyproject.toml"); file::rename(".template/tox.ini", "tox.ini"); diff --git a/examples/setuptools-rust-starter/.template/pre-script.rhai b/examples/setuptools-rust-starter/.template/pre-script.rhai index a44b6a73..0dd10361 100644 --- a/examples/setuptools-rust-starter/.template/pre-script.rhai +++ b/examples/setuptools-rust-starter/.template/pre-script.rhai @@ -1,4 +1,4 @@ -variable::set("PYO3_VERSION", "0.16.3"); +variable::set("PYO3_VERSION", "0.16.4"); file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/setup.cfg", "setup.cfg"); file::rename(".template/tox.ini", "tox.ini"); diff --git a/examples/word-count/.template/pre-script.rhai b/examples/word-count/.template/pre-script.rhai index fd959ba2..778da32d 100644 --- a/examples/word-count/.template/pre-script.rhai +++ b/examples/word-count/.template/pre-script.rhai @@ -1,4 +1,4 @@ -variable::set("PYO3_VERSION", "0.16.3"); +variable::set("PYO3_VERSION", "0.16.4"); file::rename(".template/Cargo.toml", "Cargo.toml"); file::rename(".template/tox.ini", "tox.ini"); file::delete(".template"); diff --git a/pyo3-build-config/Cargo.toml b/pyo3-build-config/Cargo.toml index 7449b1f9..fb687b0f 100644 --- a/pyo3-build-config/Cargo.toml +++ b/pyo3-build-config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3-build-config" -version = "0.16.3" +version = "0.16.4" description = "Build configuration for the PyO3 ecosystem" authors = ["PyO3 Project and Contributors "] keywords = ["pyo3", "python", "cpython", "ffi"] diff --git a/pyo3-ffi/Cargo.toml b/pyo3-ffi/Cargo.toml index e632fa91..0e6703dd 100644 --- a/pyo3-ffi/Cargo.toml +++ b/pyo3-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3-ffi" -version = "0.16.3" +version = "0.16.4" description = "Python-API bindings for the PyO3 ecosystem" authors = ["PyO3 Project and Contributors "] keywords = ["pyo3", "python", "cpython", "ffi"] @@ -35,4 +35,4 @@ abi3-py310 = ["abi3", "pyo3-build-config/abi3-py310"] [build-dependencies] -pyo3-build-config = { path = "../pyo3-build-config", version = "0.16.3", features = ["resolve-config"] } +pyo3-build-config = { path = "../pyo3-build-config", version = "0.16.4", features = ["resolve-config"] } diff --git a/pyo3-macros-backend/Cargo.toml b/pyo3-macros-backend/Cargo.toml index feef146c..b8e543cd 100644 --- a/pyo3-macros-backend/Cargo.toml +++ b/pyo3-macros-backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3-macros-backend" -version = "0.16.3" +version = "0.16.4" description = "Code generation for PyO3 package" authors = ["PyO3 Project and Contributors "] keywords = ["pyo3", "python", "cpython", "ffi"] diff --git a/pyo3-macros/Cargo.toml b/pyo3-macros/Cargo.toml index 26c4e7a5..7758fb3b 100644 --- a/pyo3-macros/Cargo.toml +++ b/pyo3-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyo3-macros" -version = "0.16.3" +version = "0.16.4" description = "Proc macros for PyO3 package" authors = ["PyO3 Project and Contributors "] keywords = ["pyo3", "python", "cpython", "ffi"] @@ -23,4 +23,4 @@ abi3 = ["pyo3-macros-backend/abi3"] proc-macro2 = { version = "1", default-features = false } quote = "1" syn = { version = "1.0.56", features = ["full", "extra-traits"] } -pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.16.3" } +pyo3-macros-backend = { path = "../pyo3-macros-backend", version = "=0.16.4" } From 3fe38307b89c54fb5e39ed3c3f73a7ffb872549e Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Thu, 14 Apr 2022 19:16:57 +0100 Subject: [PATCH 8/8] changelog: add notes from 0.15.2 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d565a662..9d64df18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -167,6 +167,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix FFI definition of `_PyLong_NumBits` to return `size_t` instead of `c_int`. [#2161](https://github.com/PyO3/pyo3/pull/2161) - Fix `TypeError` thrown when argument parsing failed missing the originating causes. [2177](https://github.com/PyO3/pyo3/pull/2178) +## [0.15.2] - 2022-04-14 + +### Packaging + +- Backport of PyPy 3.9 support from PyO3 0.16. [#2262](https://github.com/PyO3/pyo3/pull/2262) + ## [0.15.1] - 2021-11-19 ### Added @@ -1153,6 +1159,7 @@ Yanked [0.16.2]: https://github.com/pyo3/pyo3/compare/v0.16.1...v0.16.2 [0.16.1]: https://github.com/pyo3/pyo3/compare/v0.16.0...v0.16.1 [0.16.0]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.16.0 +[0.15.2]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.15.2 [0.15.1]: https://github.com/pyo3/pyo3/compare/v0.15.0...v0.15.1 [0.15.0]: https://github.com/pyo3/pyo3/compare/v0.14.5...v0.15.0 [0.14.5]: https://github.com/pyo3/pyo3/compare/v0.14.4...v0.14.5