From b08f4c02ebf748c28bdbd4bea14aac7ed5b036c1 Mon Sep 17 00:00:00 2001
From: Armin Ronacher <armin.ronacher@active-4.com>
Date: Wed, 6 Nov 2024 14:45:50 +0100
Subject: [PATCH] Upgrade pyo3 to 0.22

---
 Cargo.lock                      | 26 +++++++--------
 minijinja-py/Cargo.toml         |  2 +-
 minijinja-py/src/environment.rs | 59 ++++++++++++++++++++++++---------
 minijinja-py/src/typeconv.rs    |  2 +-
 4 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 293139a2..889246f9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1250,9 +1250,9 @@ checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
 
 [[package]]
 name = "heck"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
 name = "hello"
@@ -2371,15 +2371,15 @@ dependencies = [
 
 [[package]]
 name = "pyo3"
-version = "0.21.2"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
+checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884"
 dependencies = [
  "cfg-if",
  "indoc",
  "libc",
  "memoffset",
- "parking_lot",
+ "once_cell",
  "portable-atomic",
  "pyo3-build-config",
  "pyo3-ffi",
@@ -2390,9 +2390,9 @@ dependencies = [
 
 [[package]]
 name = "pyo3-build-config"
-version = "0.21.2"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
+checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38"
 dependencies = [
  "once_cell",
  "target-lexicon",
@@ -2400,9 +2400,9 @@ dependencies = [
 
 [[package]]
 name = "pyo3-ffi"
-version = "0.21.2"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
+checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636"
 dependencies = [
  "libc",
  "pyo3-build-config",
@@ -2410,9 +2410,9 @@ dependencies = [
 
 [[package]]
 name = "pyo3-macros"
-version = "0.21.2"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
+checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453"
 dependencies = [
  "proc-macro2",
  "pyo3-macros-backend",
@@ -2422,9 +2422,9 @@ dependencies = [
 
 [[package]]
 name = "pyo3-macros-backend"
-version = "0.21.2"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
+checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe"
 dependencies = [
  "heck",
  "proc-macro2",
diff --git a/minijinja-py/Cargo.toml b/minijinja-py/Cargo.toml
index 515f6982..31d51dd1 100644
--- a/minijinja-py/Cargo.toml
+++ b/minijinja-py/Cargo.toml
@@ -11,4 +11,4 @@ crate-type = ["cdylib"]
 [dependencies]
 minijinja = { version = "2.4.0", path = "../minijinja", features = ["loader", "json", "urlencode", "fuel", "preserve_order", "speedups", "custom_syntax"] }
 once_cell = "1.17.0"
-pyo3 = { version = "0.21.1", features = ["extension-module", "serde", "abi3-py38"] }
+pyo3 = { version = "0.22.6", features = ["extension-module", "serde", "abi3-py38"] }
diff --git a/minijinja-py/src/environment.rs b/minijinja-py/src/environment.rs
index 45973079..7640951e 100644
--- a/minijinja-py/src/environment.rs
+++ b/minijinja-py/src/environment.rs
@@ -304,7 +304,7 @@ impl Environment {
         }
         let callback: Py<PyAny> = callback.clone().unbind();
         let mut inner = self.inner.lock().unwrap();
-        inner.auto_escape_callback = Some(callback.clone());
+        inner.auto_escape_callback = Python::with_gil(|py| Some(callback.clone_ref(py)));
         inner
             .env
             .set_auto_escape_callback(move |name: &str| -> AutoEscape {
@@ -341,8 +341,14 @@ impl Environment {
     }
 
     #[getter]
-    pub fn get_auto_escape_callback(&self) -> PyResult<Option<Py<PyAny>>> {
-        Ok(self.inner.lock().unwrap().auto_escape_callback.clone())
+    pub fn get_auto_escape_callback(&self, py: Python<'_>) -> PyResult<Option<Py<PyAny>>> {
+        Ok(self
+            .inner
+            .lock()
+            .unwrap()
+            .auto_escape_callback
+            .as_ref()
+            .map(|x| x.clone_ref(py)))
     }
 
     /// Sets a finalizer.
@@ -355,7 +361,9 @@ impl Environment {
         }
         let callback: Py<PyAny> = callback.clone().unbind();
         let mut inner = self.inner.lock().unwrap();
-        inner.finalizer_callback = Some(callback.clone());
+        Python::with_gil(|py| {
+            inner.finalizer_callback = Some(callback.clone_ref(py));
+        });
         inner.env.set_formatter(move |output, state, value| {
             Python::with_gil(|py| -> Result<(), Error> {
                 let maybe_new_value = bind_state(state, || -> Result<_, Error> {
@@ -382,8 +390,14 @@ impl Environment {
     }
 
     #[getter]
-    pub fn get_finalizer(&self) -> PyResult<Option<Py<PyAny>>> {
-        Ok(self.inner.lock().unwrap().finalizer_callback.clone())
+    pub fn get_finalizer(&self, py: Python<'_>) -> PyResult<Option<Py<PyAny>>> {
+        Ok(self
+            .inner
+            .lock()
+            .unwrap()
+            .finalizer_callback
+            .as_ref()
+            .map(|x| x.clone_ref(py)))
     }
 
     /// Sets a loader function for the environment.
@@ -403,7 +417,9 @@ impl Environment {
             }
         };
         let mut inner = self.inner.lock().unwrap();
-        inner.loader.clone_from(&callback);
+        Python::with_gil(|py| {
+            inner.loader = callback.as_ref().map(|x| x.clone_ref(py));
+        });
 
         if let Some(callback) = callback {
             inner.env.set_loader(move |name| {
@@ -426,8 +442,13 @@ impl Environment {
 
     /// Returns the current loader.
     #[getter]
-    pub fn get_loader(&self) -> Option<Py<PyAny>> {
-        self.inner.lock().unwrap().loader.clone()
+    pub fn get_loader(&self, py: Python<'_>) -> Option<Py<PyAny>> {
+        self.inner
+            .lock()
+            .unwrap()
+            .loader
+            .as_ref()
+            .map(|x| x.clone_ref(py))
     }
 
     /// Sets a new path join callback.
@@ -438,7 +459,9 @@ impl Environment {
         }
         let callback: Py<PyAny> = callback.clone().unbind();
         let mut inner = self.inner.lock().unwrap();
-        inner.path_join_callback = Some(callback.clone());
+        Python::with_gil(|py| {
+            inner.path_join_callback = Some(callback.clone_ref(py));
+        });
         inner.env.set_path_join_callback(move |name, parent| {
             Python::with_gil(|py| {
                 let callback = callback.bind(py);
@@ -456,14 +479,19 @@ impl Environment {
 
     /// Returns the current path join callback.
     #[getter]
-    pub fn get_path_join_callback(&self) -> Option<Py<PyAny>> {
-        self.inner.lock().unwrap().path_join_callback.clone()
+    pub fn get_path_join_callback(&self, py: Python<'_>) -> Option<Py<PyAny>> {
+        self.inner
+            .lock()
+            .unwrap()
+            .path_join_callback
+            .as_ref()
+            .map(|x| x.clone_ref(py))
     }
 
     /// Triggers a reload of the templates.
-    pub fn reload(&self) -> PyResult<()> {
+    pub fn reload(&self, py: Python<'_>) -> PyResult<()> {
         let mut inner = self.inner.lock().unwrap();
-        let loader = inner.loader.as_ref().cloned();
+        let loader = inner.loader.as_ref().map(|x| x.clone_ref(py));
         if loader.is_some() {
             inner.env.clear_templates();
         }
@@ -633,11 +661,12 @@ impl Environment {
     #[pyo3(signature = (template_name, /, **ctx))]
     pub fn render_template(
         slf: PyRef<'_, Self>,
+        py: Python<'_>,
         template_name: &str,
         ctx: Option<&Bound<'_, PyDict>>,
     ) -> PyResult<String> {
         if slf.reload_before_render.load(Ordering::Relaxed) {
-            slf.reload()?;
+            slf.reload(py)?;
         }
         bind_environment(slf.as_ptr(), || {
             let inner = slf.inner.lock().unwrap();
diff --git a/minijinja-py/src/typeconv.rs b/minijinja-py/src/typeconv.rs
index eac37a3a..d38b73f4 100644
--- a/minijinja-py/src/typeconv.rs
+++ b/minijinja-py/src/typeconv.rs
@@ -187,7 +187,7 @@ fn to_python_value_impl(py: Python<'_>, value: Value) -> PyResult<Py<PyAny>> {
     // conversion.  That means that when passing the object back to Python we
     // extract the retained raw Python reference.
     if let Some(pyobj) = value.downcast_object_ref::<DynamicObject>() {
-        return Ok(pyobj.inner.clone());
+        return Ok(pyobj.inner.clone_ref(py));
     }
 
     if let Some(obj) = value.as_object() {