From f777372eedcb409d82e10c5c2cde70db8b71de04 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sun, 3 Apr 2022 20:58:51 +0200 Subject: [PATCH] Limit the intern! macro to strings and intern the string contents in addition to the reference. --- CHANGELOG.md | 2 +- src/once_cell.rs | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bcb328b..807c6cc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added methods on `InterpreterConfig` to run Python scripts using the configured executable. [#2092](https://github.com/PyO3/pyo3/pull/2092) - Added FFI definitions for `PyType_FromModuleAndSpec`, `PyType_GetModule`, `PyType_GetModuleState` and `PyModule_AddType`. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Add `PyString::intern` to enable usage of the Python's built-in string interning. [#2268](https://github.com/PyO3/pyo3/pull/2268) -- Add `intern!` macro which can be used to amortize the cost of creating Python objects by storing them inside a `GILOnceCell`. [#2269](https://github.com/PyO3/pyo3/pull/2269) +- Add `intern!` macro which can be used to amortize the cost of creating Python strings by storing them inside a `GILOnceCell`. [#2269](https://github.com/PyO3/pyo3/pull/2269) ### Changed diff --git a/src/once_cell.rs b/src/once_cell.rs index bed7a8bc..b759832f 100644 --- a/src/once_cell.rs +++ b/src/once_cell.rs @@ -111,12 +111,11 @@ impl GILOnceCell { } } -/// Converts `value` into a Python object and stores it in static storage. The same Python object -/// is returned on each invocation. +/// Interns `text` as a Python string and stores a reference to it in static storage. /// -/// Because it is stored in a static, this object's destructor will not run. +/// A reference to the same Python string is returned on each invocation. /// -/// # Example: Using `intern!` to avoid needlessly recreating the same object +/// # Example: Using `intern!` to avoid needlessly recreating the same Python string /// /// ``` /// use pyo3::intern; @@ -126,7 +125,7 @@ impl GILOnceCell { /// fn create_dict(py: Python<'_>) -> PyResult<&PyDict> { /// let dict = PyDict::new(py); /// // 👇 A new `PyString` is created -/// // for every call of this function +/// // for every call of this function. /// dict.set_item("foo", 42)?; /// Ok(dict) /// } @@ -142,14 +141,12 @@ impl GILOnceCell { /// ``` #[macro_export] macro_rules! intern { - ($py: expr, $value: expr) => {{ - static INTERNED: $crate::once_cell::GILOnceCell<$crate::PyObject> = + ($py: expr, $text: literal) => {{ + static INTERNED: $crate::once_cell::GILOnceCell<$crate::Py<$crate::types::PyString>> = $crate::once_cell::GILOnceCell::new(); INTERNED - .get_or_init($py, || { - $crate::conversion::ToPyObject::to_object($value, $py) - }) + .get_or_init($py, || $crate::types::PyString::intern($py, $text).into()) .as_ref($py) }}; }